[ufl] 03/06: New upstream version 2016.2.0

Johannes Ring johannr-guest at moszumanska.debian.org
Thu Dec 1 13:52:50 UTC 2016


This is an automated email from the git hooks/post-receive script.

johannr-guest pushed a commit to branch master
in repository ufl.

commit 02f7ca9b0bf037b5be15ca14d429daea07c8c76c
Author: Johannes Ring <johannr at simula.no>
Date:   Thu Dec 1 14:19:15 2016 +0100

    New upstream version 2016.2.0
---
 .gitignore                                         |    5 -
 AUTHORS                                            |   30 +
 ChangeLog                                          |   35 +
 README                                             |  151 ---
 README.rst                                         |   66 ++
 demo/Poisson.ufl                                   |   10 +-
 doc/man/man1/form2ufl.1.gz                         |  Bin 616 -> 0 bytes
 doc/man/man1/ufl-analyse.1.gz                      |  Bin 791 -> 809 bytes
 doc/man/man1/ufl-convert.1.gz                      |  Bin 939 -> 957 bytes
 doc/man/man1/ufl-version.1.gz                      |  Bin 594 -> 596 bytes
 doc/man/man1/ufl2py.1.gz                           |  Bin 626 -> 654 bytes
 doc/sphinx/README                                  |   17 +-
 doc/sphinx/generate-apidoc                         |   29 -
 doc/sphinx/source/api-doc/modules.rst              |    7 -
 doc/sphinx/source/api-doc/ufl.algorithms.rst       |  270 ------
 doc/sphinx/source/api-doc/ufl.core.rst             |   70 --
 doc/sphinx/source/api-doc/ufl.corealg.rst          |   38 -
 doc/sphinx/source/api-doc/ufl.finiteelement.rst    |  118 ---
 doc/sphinx/source/api-doc/ufl.formatting.rst       |   54 --
 doc/sphinx/source/api-doc/ufl.rst                  |  354 -------
 doc/sphinx/source/api-doc/ufl.utils.rst            |  102 --
 doc/sphinx/source/conf.py                          |   21 +-
 doc/sphinx/source/index.rst                        |  118 +--
 doc/sphinx/source/installation.rst                 |   47 +
 doc/sphinx/source/manual.rst                       |   16 +
 doc/sphinx/source/{user => manual}/algorithms.rst  |  196 ++--
 .../source/{user => manual}/command_line_utils.rst |   23 +-
 doc/sphinx/source/{user => manual}/examples.rst    |   93 +-
 .../source/{user => manual}/form_language.rst      |  256 +++--
 .../{user => manual}/internal_representation.rst   |   14 +-
 .../source/{user => manual}/introduction.rst       |    7 +-
 doc/sphinx/source/{user => manual}/user_manual.rst |    0
 doc/sphinx/source/releases.rst                     |    5 +
 doc/sphinx/source/releases/next.rst                |   35 +-
 doc/sphinx/source/releases/v1.6.0.rst              |    7 +-
 doc/sphinx/source/releases/v2016.1.0.rst           |   27 +
 release.conf                                       |    6 -
 scripts/ufl-analyse                                |    7 +-
 scripts/ufl-convert                                |  102 +-
 scripts/ufl-version                                |   10 +-
 scripts/ufl2py                                     |    3 +-
 setup.cfg                                          |    3 +
 setup.py                                           |  103 +-
 test/conftest.py                                   |    4 +
 test/sourceme.sh                                   |    5 -
 test/test_algorithms.py                            |    1 -
 test/test_analyse_demos.py                         |   73 +-
 test/test_apply_algebra_lowering.py                |   47 +-
 test/test_apply_function_pullbacks.py              |  112 +--
 test/test_apply_restrictions.py                    |    7 +-
 test/test_arithmetic.py                            |   17 +-
 test/test_automatic_differentiation.py             |  157 +--
 test/test_book_snippets.py                         |  154 ++-
 test/test_change_to_reference_frame.py             |   20 +-
 test/test_check_arities.py                         |    1 +
 test/test_classcoverage.py                         |   53 +-
 test/test_degree_estimation.py                     |    4 +-
 test/test_derivative.py                            |  193 ++--
 test/test_diff.py                                  |    4 +-
 test/test_domains.py                               |    8 +-
 test/test_elements.py                              |    4 +
 test/test_expand_indices.py                        |   34 +-
 test/test_form.py                                  |   19 +-
 test/test_future_division.py                       |    5 +-
 test/test_grad.py                                  |   23 +-
 test/test_indexing.py                              |   12 +-
 test/test_indices.py                               |   27 +-
 test/test_literals.py                              |   28 +-
 test/test_measures.py                              |   16 +-
 test/test_mock_expr.py                             |   76 --
 test/test_new_ad.py                                |   26 +-
 test/test_piecewise_checks.py                      |    2 +-
 test/test_reference_shapes.py                      |    5 +-
 test/test_scratch.py                               |   73 +-
 test/test_signature.py                             |   91 +-
 test/test_simplify.py                              |   28 +-
 test/test_split.py                                 |   44 +-
 test/test_str.py                                   |   38 +-
 test/test_tensoralgebra.py                         |   33 +-
 test/test_utilities.py                             |   25 +-
 ufl/__init__.py                                    |  205 ++--
 ufl/algebra.py                                     |   97 +-
 ufl/algorithms/__init__.py                         |  103 +-
 ufl/algorithms/ad.py                               |    6 +-
 ufl/algorithms/analysis.py                         |   41 +-
 ufl/algorithms/apply_algebra_lowering.py           |   43 +-
 ufl/algorithms/apply_derivatives.py                |  416 ++++----
 ufl/algorithms/apply_function_pullbacks.py         |   92 +-
 ufl/algorithms/apply_geometry_lowering.py          |  105 +-
 ufl/algorithms/apply_integral_scaling.py           |   26 +-
 ufl/algorithms/apply_restrictions.py               |  178 ++--
 ufl/algorithms/argument_dependencies.py            |  175 ----
 ufl/algorithms/change_to_reference.py              |  146 +--
 ufl/algorithms/check_arities.py                    |   27 +-
 ufl/algorithms/check_restrictions.py               |   40 +-
 ufl/algorithms/checks.py                           |   38 +-
 ufl/algorithms/compute_form_data.py                |  183 ++--
 ufl/algorithms/domain_analysis.py                  |   87 +-
 ufl/algorithms/elementtransformations.py           |   16 +-
 ufl/algorithms/estimate_degrees.py                 |  118 +--
 ufl/algorithms/expand_compounds.py                 |    3 +-
 ufl/algorithms/expand_indices.py                   |   78 +-
 ufl/algorithms/formdata.py                         |   67 +-
 ufl/algorithms/formfiles.py                        |  161 ++--
 ufl/algorithms/formsplitter.py                     |    4 +-
 ufl/algorithms/formtransformations.py              |   76 +-
 ufl/algorithms/forward_ad.py                       | 1018 --------------------
 ufl/algorithms/map_integrands.py                   |   18 +-
 ufl/algorithms/multifunction.py                    |    6 +-
 ufl/algorithms/pdiffs.py                           |  247 -----
 ufl/algorithms/predicates.py                       |   50 -
 ufl/algorithms/renumbering.py                      |   13 +-
 ufl/algorithms/replace.py                          |   13 +-
 ufl/algorithms/signature.py                        |   67 +-
 ufl/algorithms/transformer.py                      |   48 +-
 ufl/algorithms/traversal.py                        |    8 +-
 ufl/argument.py                                    |   63 +-
 ufl/assertions.py                                  |   28 +-
 ufl/cell.py                                        |  259 +++--
 ufl/checks.py                                      |   21 +-
 ufl/classes.py                                     |   56 +-
 ufl/coefficient.py                                 |   39 +-
 ufl/compound_expressions.py                        |  111 ++-
 ufl/conditional.py                                 |  118 ++-
 ufl/constantvalue.py                               |  146 +--
 ufl/core/compute_expr_hash.py                      |   13 +-
 ufl/core/expr.py                                   |  311 +++---
 ufl/core/multiindex.py                             |   49 +-
 ufl/core/operator.py                               |   28 +-
 ufl/core/terminal.py                               |   17 +-
 ufl/core/ufl_id.py                                 |   35 +-
 ufl/core/ufl_type.py                               |  129 ++-
 ufl/corealg/map_dag.py                             |   22 +-
 ufl/corealg/multifunction.py                       |   57 +-
 ufl/corealg/traversal.py                           |   30 +-
 ufl/differentiation.py                             |  208 ++--
 ufl/domain.py                                      |  140 +--
 ufl/equation.py                                    |   23 +-
 ufl/exprcontainers.py                              |   31 +-
 ufl/exprequals.py                                  |   40 +-
 ufl/exproperators.py                               |  157 +--
 ufl/finiteelement/__init__.py                      |    7 +-
 ufl/finiteelement/brokenelement.py                 |   13 +-
 ufl/finiteelement/elementlist.py                   |  347 ++++---
 ufl/finiteelement/enrichedelement.py               |   46 +-
 ufl/finiteelement/facetelement.py                  |   13 +-
 ufl/finiteelement/finiteelement.py                 |  147 ++-
 ufl/finiteelement/finiteelementbase.py             |  126 ++-
 ufl/finiteelement/hdivcurl.py                      |   53 +-
 ufl/finiteelement/interiorelement.py               |   13 +-
 ufl/finiteelement/mixedelement.py                  |  178 ++--
 ufl/finiteelement/outerproductelement.py           |   83 --
 ufl/finiteelement/restrictedelement.py             |   50 +-
 ufl/finiteelement/tensorproductelement.py          |   80 +-
 ufl/finiteelement/traceelement.py                  |   49 -
 ufl/form.py                                        |  232 +++--
 ufl/formatting/graph.py                            |   62 +-
 ufl/formatting/latextools.py                       |   28 +-
 ufl/formatting/printing.py                         |   41 +-
 ufl/formatting/ufl2dot.py                          |  138 +--
 ufl/formatting/ufl2latex.py                        |  175 ++--
 ufl/formoperators.py                               |  155 +--
 ufl/functionspace.py                               |   69 +-
 ufl/geometry.py                                    |  158 ++-
 ufl/index_combination_utils.py                     |   36 +-
 ufl/indexed.py                                     |   68 +-
 ufl/indexing.py                                    |   22 -
 ufl/indexsum.py                                    |   35 +-
 ufl/integral.py                                    |   89 +-
 ufl/log.py                                         |   74 +-
 ufl/mathfunctions.py                               |   83 +-
 ufl/measure.py                                     |  246 +++--
 ufl/objects.py                                     |   23 +-
 ufl/operators.py                                   |  309 +++---
 ufl/permutation.py                                 |   31 +-
 ufl/precedence.py                                  |   30 +-
 ufl/protocols.py                                   |    6 +-
 ufl/referencevalue.py                              |   10 +-
 ufl/restriction.py                                 |   21 +-
 ufl/sobolevspace.py                                |   18 +-
 ufl/sorting.py                                     |  237 ++---
 ufl/split_functions.py                             |  142 ++-
 ufl/tensoralgebra.py                               |  174 ++--
 ufl/tensors.py                                     |  143 +--
 ufl/utils/counted.py                               |    7 +-
 ufl/utils/derivativetuples.py                      |    9 +-
 ufl/utils/dicts.py                                 |   13 +-
 ufl/utils/formatting.py                            |   13 +-
 ufl/utils/indexflattening.py                       |    5 +-
 ufl/utils/py23.py                                  |   60 ++
 ufl/utils/sequences.py                             |   14 +-
 ufl/utils/sorting.py                               |   12 +-
 ufl/utils/stacks.py                                |    4 +-
 ufl/utils/system.py                                |   51 -
 ufl/utils/timer.py                                 |   45 -
 ufl/utils/ufltypedicts.py                          |    5 +-
 ufl/variable.py                                    |   31 +-
 197 files changed, 6841 insertions(+), 7562 deletions(-)

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 85fec14..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*.pyc
-*.py~
-build/
-test/*_debug.py
-test/UFL.log
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..f70d72d
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,30 @@
+Authors
+=======
+
+Authors:
+  | Martin Sandve Alnæs   <martinal at simula.no>
+  | Anders Logg           <logg at chalmers.se>
+
+Contributors:
+  | Kristian B. Ølgaard   <k.b.oelgaard at gmail.com>
+  | Garth N. Wells        <gnw20 at cam.ac.uk>
+  | Marie E. Rognes       <meg at simula.no>
+  | Kent-Andre Mardal     <kent-and at simula.no>
+  | Johan Hake            <hake at simula.no>
+  | David Ham             <david.ham at imperial.ac.uk>
+  | Florian Rathgeber     <f.rathgeber10 at imperial.ac.uk>
+  | Andrew T. T. McRae    <a.t.t.mcrae at bath.ac.uk>
+  | Lawrence Mitchell     <lawrence.mitchell at imperial.ac.uk>
+  | Johannes Ring         <johannr at simula.no>
+  | Aslak Bergersen       <aslak.bergersen at gmail.com>
+  | Chris Richardson      <chris at bpi.cam.ac.uk>
+  | Massimiliano Leoni    <leoni.massimiliano1 at gmail.com>
+  | Jan Blechta           <blechta at karlin.mff.cuni.cz>
+  | Graham Markall        <grm08 at doc.ic.ac.uk>
+  | Lizao Li              <lzlarryli at gmail.com>
+  | Miklos Homolya        <m.homolya14 at imperial.ac.uk>
+  | Matthias Liertzer     <matthias at liertzer.at>
+  | Maximilian Albert     <maximilian.albert at gmail.com>
+  | Corrado Maurini       <corrado.maurini at upmc.fr>
+  | Jack S. Hale          <mail at jackhale.co.uk>
+  | Tuomas Airaksinen     <tuomas.airaksinen at gmail.com>
diff --git a/ChangeLog b/ChangeLog
index 3b1fc9e..83209cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2016.2.0 [2016-11-30]
+  - Add call operator syntax to Form to replace arguments and
+    coefficients. This makes it easier to e.g. express the norm
+    defined by a bilinear form as a functional. Example usage:
+      # Equivalent to replace(a, {u: f, v: f})
+      M = a(f, f)
+      # Equivalent to replace(a, {f:1})
+      c = a(coefficients={f:1})
+ - Add call operator syntax to Form to replace arguments and coefficients:
+     a(f, g) == replace(a, {u: f, v: g})
+     a(coefficients={f:1}) == replace(a, {f:1})
+ - Add @ operator to Form: form @ f == action(form, f) (python 3.5+ only)
+ - Reduce noise in Mesh str such that print(form) gets more short and readable
+ - Fix repeated split(function) for arbitrary nested elements
+ - EnrichedElement: Remove +/* warning
+    In the distant past, A + B => MixedElement([A, B]).  The change that
+    A + B => EnrichedElement([A, B]) was made in d622c74 (22 March 2010).
+    A warning was introduced in fcbc5ff (26 March 2010) that the meaning of
+    "+" had changed, and that users wanting a MixedElement should use "*"
+    instead.  People have, presumably, been seeing this warning for 6 1/2
+    years by now, so it's probably safe to remove.
+ - Rework TensorProductElement implementation, replaces OuterProductElement
+ - Rework TensorProductCell implementation, replaces OuterProductCell
+ - Remove OuterProductVectorElement and OuterProductTensorElement
+ - Add FacetElement and InteriorElement
+ - Add Hellan-Herrmann-Johnson element
+ - Add support for double covariant and contravariant mappings in mixed elements
+ - Support discontinuous Taylor elements on all simplices
+ - Some more performance improvements
+ - Minor bugfixes
+ - Improve Python 3 support
+ - More permissive in integer types accepted some places
+ - Make ufl pass almost all flake8 tests
+ - Add bitbucket pipelines testing
+ - Improve documentation
 2016.1.0 [2016-06-23]
  - Add operator A^(i,j) := as_tensor(A, (i,j))
  - Updates to old manual for publishing on fenics-ufl.readthedocs.org
diff --git a/README b/README
deleted file mode 100644
index d4cb0eb..0000000
--- a/README
+++ /dev/null
@@ -1,151 +0,0 @@
-===========================
-UFL - Unified Form Language
-===========================
-
-The Unified Form Language (UFL) is a domain specific language for
-declaration of finite element discretizations of variational
-forms. More precisely, it defines a flexible interface for choosing
-finite element spaces and defining expressions for weak forms in a
-notation close to mathematical notation.
-
-Authors:
-  | Martin Sandve Alnæs   <martinal at simula.no>
-  | Anders Logg           <logg at chalmers.se>
-
-Contributors:
-  | Kristian B. Ølgaard   <k.b.oelgaard at gmail.com>
-  | Garth N. Wells        <gnw20 at cam.ac.uk>
-  | Marie E. Rognes       <meg at simula.no>
-  | Kent-Andre Mardal     <kent-and at simula.no>
-  | Johan Hake            <hake at simula.no>
-  | David Ham             <david.ham at imperial.ac.uk>
-  | Florian Rathgeber     <f.rathgeber10 at imperial.ac.uk>
-  | Andrew McRae          <a.mcrae12 at imperial.ac.uk>
-  | Lawrence Mitchell     <lawrence.mitchell at imperial.ac.uk>
-  | Johannes Ring         <johannr at simula.no>
-
-UFL is described in the paper:
-
-Alnæs, M. S., Logg A., Ølgaard, K. B., Rognes, M. E. and Wells,
-G. N. (2014).  Unified Form Language: A domain-specific language for
-weak formulations of partial differential equations.  *ACM
-Transactions on Mathematical Software* 40(2), Article 9, 37 pages.
-<http://dx.doi.org/doi:10.1145/2566630>,
-<http://arxiv.org/abs/1211.4047>
-
-
-Documentation
-=============
-
-The UFL documentation is hosted at http://fenics-ufl.rtfd.org/.
-
-
-Installation
-============
-
-Linux::
-
-  sudo python setup.py install
-
-
-Directories
-===========
-
-- ufl/
-
-  All source code for the UFL implementation.
-
-- scripts/
-
-  Commandline utilities like "ufl-analyse", "ufl-convert" and "form2ufl".
-
-- demo/
-
-  Several ufl form files which demonstrates the use of the form language.
-
-- doc/
-
-  The UFL documentation resides here. See doc/sphinx/README for how to
-  generate the docucmentation.
-
-- test/
-
-  Unit tests for the UFL implementation. Run all tests by typing
-  "python test.py" inside the test/ directory.
-
-
-Utilities
-=========
-
-For more information about the utilities, type::
-
-  ufl-analyse -h
-  ufl-convert -h
-  form2ufl -h
-
-after installation.
-
-
-About the Python modules
-========================
-
-The global namespace of the module ufl contains the entire UFL
-language::
-
-  from ufl import *
-
-Form compilers may want to import additional implementation details
-like::
-
-  from ufl.classes import *
-
-and::
-
-  from ufl.algorithms import *
-
-Importing a .ufl file can be done easily from Python::
-
-  from ufl.algorithms import load_ufl_file
-  filedata = load_ufl_file("filename.ufl")
-  forms = filedata.forms
-  elements = filedata.elements
-
-to get lists of forms and elements from the .ufl file, or::
-
-  from ufl.algorithms import load_forms
-  forms = load_forms("filename.ufl")
-
-to get a list of forms in the .ufl file.
-
-
-Contact
-=======
-
-Send feature requests and questions to
-
-  fenics-dev at googlegroups.com
-
-The Git source repository for UFL is located at
-
-  https://bitbucket.org/fenics-project/ufl
-
-and bugs can be registered at
-
-  https://bitbucket.org/fenics-project/ufl/issues
-
-
-License
-=======
-
-UFL is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-UFL is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with UFL. If not, see <http://www.gnu.org/licenses/>.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..32db38c
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,66 @@
+===========================
+UFL - Unified Form Language
+===========================
+
+The Unified Form Language (UFL) is a domain specific language for
+declaration of finite element discretizations of variational
+forms. More precisely, it defines a flexible interface for choosing
+finite element spaces and defining expressions for weak forms in a
+notation close to mathematical notation.
+
+UFL is part of the FEniCS Project.
+
+For more information, visit http://www.fenicsproject.org
+
+
+Documentation
+=============
+
+Documentation can be viewed at http://fenics-ufl.readthedocs.org/.
+
+.. image:: https://readthedocs.org/projects/fenics-ufl/badge/?version=latest
+   :target: http://fenics.readthedocs.io/projects/ufl/en/latest/?badge=latest
+   :alt: Documentation Status
+
+
+Automated Testing
+=================
+
+We use Bitbucket Pipelines and Atlassian Bamboo to perform automated
+testing.
+
+.. image:: https://bitbucket-badges.useast.atlassian.io/badge/fenics-project/ufl.svg
+   :target: https://bitbucket.org/fenics-project/ufl/addon/pipelines/home
+   :alt: Pipelines Build Status
+
+.. image:: http://fenics-bamboo.simula.no:8085/plugins/servlet/wittified/build-status/UFL-UD
+   :target: http://fenics-bamboo.simula.no:8085/browse/UFL-UD/latest
+   :alt: Bamboo Build Status
+
+
+Code Coverage
+=============
+
+Code coverage reports can be viewed at
+https://coveralls.io/repos/bitbucket/fenics-project/ufl.
+
+.. image:: https://coveralls.io/repos/bitbucket/fenics-project/ufl/badge.svg?branch=master
+   :target: https://coveralls.io/bitbucket/fenics-project/ufl?branch=master
+   :alt: Coverage Status
+
+
+License
+=======
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/demo/Poisson.ufl b/demo/Poisson.ufl
index 693f3cd..0a09bc1 100644
--- a/demo/Poisson.ufl
+++ b/demo/Poisson.ufl
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
 # Copyright (C) 2004-2008 Anders Logg
 #
 # This file is part of UFL.
@@ -15,7 +16,7 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
-# Modified by Martin Sandve Alnes, 2009
+# Modified by Martin Sandve Alnæs, 2009
 #
 # Last changed: 2009-03-02
 #
@@ -27,8 +28,5 @@ u = TrialFunction(element)
 v = TestFunction(element)
 f = Coefficient(element)
 
-dx0_1 = dx(0, {"quadrature_order": 1})
-dx0_2 = dx(0, {"quadrature_order": 2})
-
-a = dot(grad(v), grad(u))*dx0_1
-L = v*f*dx0_2
+a = dot(grad(v), grad(u))*dx(degree=1)
+L = v*f*dx(degree=2)
diff --git a/doc/man/man1/form2ufl.1.gz b/doc/man/man1/form2ufl.1.gz
deleted file mode 100644
index 999cee1..0000000
Binary files a/doc/man/man1/form2ufl.1.gz and /dev/null differ
diff --git a/doc/man/man1/ufl-analyse.1.gz b/doc/man/man1/ufl-analyse.1.gz
index 028e0ee..25cfcd6 100644
Binary files a/doc/man/man1/ufl-analyse.1.gz and b/doc/man/man1/ufl-analyse.1.gz differ
diff --git a/doc/man/man1/ufl-convert.1.gz b/doc/man/man1/ufl-convert.1.gz
index 085eef5..aba80fa 100644
Binary files a/doc/man/man1/ufl-convert.1.gz and b/doc/man/man1/ufl-convert.1.gz differ
diff --git a/doc/man/man1/ufl-version.1.gz b/doc/man/man1/ufl-version.1.gz
index 6a8436a..9b80b50 100644
Binary files a/doc/man/man1/ufl-version.1.gz and b/doc/man/man1/ufl-version.1.gz differ
diff --git a/doc/man/man1/ufl2py.1.gz b/doc/man/man1/ufl2py.1.gz
index fb69e70..ab6e442 100644
Binary files a/doc/man/man1/ufl2py.1.gz and b/doc/man/man1/ufl2py.1.gz differ
diff --git a/doc/sphinx/README b/doc/sphinx/README
index 57dd5aa..d646b28 100644
--- a/doc/sphinx/README
+++ b/doc/sphinx/README
@@ -3,25 +3,18 @@ Sphinx documentation
 ====================
 
 UFL is documented using Sphinx and reStructured text. The
-documnentation is hosted at http://fenics-ufl.readthedocs.org/. The
+documentation is hosted at http://fenics-ufl.readthedocs.org/. The
 online documentation is automatically updated upon pushes to the UFL
 master branch.
 
 
-Updating the API documentation
-==============================
-
-If the UFL API is changed, the script::
-
-    ./generate-apidoc
-
-must be run to update the autodoc file. The script can be run from any
-directory.
-
-
 Building the documentation locally
 ==================================
 
 The HTML documentation can be built locally using::
 
     make html
+
+In order for changes in the docstring to be propagated to the html
+pages, ufl must be installed anew.  In other words, sphinx reads the
+docstrings from the installed code, not the source code.
diff --git a/doc/sphinx/generate-apidoc b/doc/sphinx/generate-apidoc
deleted file mode 100755
index c36179d..0000000
--- a/doc/sphinx/generate-apidoc
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (C) 2015 Garth N. Wells
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
-# This script calls sphinx-apidoc to generate files ready for autodoc
-
-echo ""
-echo "--- Generating UFL autodoc RST files"
-echo ""
-
-# Get location of Sphinx files
-SPHINX_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-SPHINX_SOURCE_DIR=$SPHINX_DIR/source
-
-# Generate .rst files ready for autodoc
-sphinx-apidoc -f -d 1 -o $SPHINX_SOURCE_DIR/api-doc $SPHINX_DIR/../../ufl
diff --git a/doc/sphinx/source/api-doc/modules.rst b/doc/sphinx/source/api-doc/modules.rst
deleted file mode 100644
index ffe8d42..0000000
--- a/doc/sphinx/source/api-doc/modules.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-ufl
-===
-
-.. toctree::
-   :maxdepth: 1
-
-   ufl
diff --git a/doc/sphinx/source/api-doc/ufl.algorithms.rst b/doc/sphinx/source/api-doc/ufl.algorithms.rst
deleted file mode 100644
index c61f659..0000000
--- a/doc/sphinx/source/api-doc/ufl.algorithms.rst
+++ /dev/null
@@ -1,270 +0,0 @@
-ufl.algorithms package
-======================
-
-Submodules
-----------
-
-ufl.algorithms.ad module
-------------------------
-
-.. automodule:: ufl.algorithms.ad
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.analysis module
-------------------------------
-
-.. automodule:: ufl.algorithms.analysis
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.apply_algebra_lowering module
---------------------------------------------
-
-.. automodule:: ufl.algorithms.apply_algebra_lowering
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.apply_derivatives module
----------------------------------------
-
-.. automodule:: ufl.algorithms.apply_derivatives
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.apply_function_pullbacks module
-----------------------------------------------
-
-.. automodule:: ufl.algorithms.apply_function_pullbacks
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.apply_geometry_lowering module
----------------------------------------------
-
-.. automodule:: ufl.algorithms.apply_geometry_lowering
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.apply_integral_scaling module
---------------------------------------------
-
-.. automodule:: ufl.algorithms.apply_integral_scaling
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.apply_restrictions module
-----------------------------------------
-
-.. automodule:: ufl.algorithms.apply_restrictions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.argument_dependencies module
--------------------------------------------
-
-.. automodule:: ufl.algorithms.argument_dependencies
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.change_to_reference module
------------------------------------------
-
-.. automodule:: ufl.algorithms.change_to_reference
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.check_arities module
------------------------------------
-
-.. automodule:: ufl.algorithms.check_arities
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.check_restrictions module
-----------------------------------------
-
-.. automodule:: ufl.algorithms.check_restrictions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.checks module
-----------------------------
-
-.. automodule:: ufl.algorithms.checks
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.compute_form_data module
----------------------------------------
-
-.. automodule:: ufl.algorithms.compute_form_data
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.domain_analysis module
--------------------------------------
-
-.. automodule:: ufl.algorithms.domain_analysis
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.elementtransformations module
---------------------------------------------
-
-.. automodule:: ufl.algorithms.elementtransformations
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.estimate_degrees module
---------------------------------------
-
-.. automodule:: ufl.algorithms.estimate_degrees
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.expand_compounds module
---------------------------------------
-
-.. automodule:: ufl.algorithms.expand_compounds
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.expand_indices module
-------------------------------------
-
-.. automodule:: ufl.algorithms.expand_indices
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.formdata module
-------------------------------
-
-.. automodule:: ufl.algorithms.formdata
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.formfiles module
--------------------------------
-
-.. automodule:: ufl.algorithms.formfiles
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.formtransformations module
------------------------------------------
-
-.. automodule:: ufl.algorithms.formtransformations
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.forward_ad module
---------------------------------
-
-.. automodule:: ufl.algorithms.forward_ad
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.map_integrands module
-------------------------------------
-
-.. automodule:: ufl.algorithms.map_integrands
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.multifunction module
------------------------------------
-
-.. automodule:: ufl.algorithms.multifunction
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.pdiffs module
-----------------------------
-
-.. automodule:: ufl.algorithms.pdiffs
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.predicates module
---------------------------------
-
-.. automodule:: ufl.algorithms.predicates
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.renumbering module
----------------------------------
-
-.. automodule:: ufl.algorithms.renumbering
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.replace module
------------------------------
-
-.. automodule:: ufl.algorithms.replace
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.signature module
--------------------------------
-
-.. automodule:: ufl.algorithms.signature
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.transformer module
----------------------------------
-
-.. automodule:: ufl.algorithms.transformer
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.algorithms.traversal module
--------------------------------
-
-.. automodule:: ufl.algorithms.traversal
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl.algorithms
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/api-doc/ufl.core.rst b/doc/sphinx/source/api-doc/ufl.core.rst
deleted file mode 100644
index d1e0564..0000000
--- a/doc/sphinx/source/api-doc/ufl.core.rst
+++ /dev/null
@@ -1,70 +0,0 @@
-ufl.core package
-================
-
-Submodules
-----------
-
-ufl.core.compute_expr_hash module
----------------------------------
-
-.. automodule:: ufl.core.compute_expr_hash
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.core.expr module
---------------------
-
-.. automodule:: ufl.core.expr
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.core.multiindex module
---------------------------
-
-.. automodule:: ufl.core.multiindex
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.core.operator module
-------------------------
-
-.. automodule:: ufl.core.operator
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.core.terminal module
-------------------------
-
-.. automodule:: ufl.core.terminal
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.core.ufl_id module
-----------------------
-
-.. automodule:: ufl.core.ufl_id
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.core.ufl_type module
-------------------------
-
-.. automodule:: ufl.core.ufl_type
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl.core
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/api-doc/ufl.corealg.rst b/doc/sphinx/source/api-doc/ufl.corealg.rst
deleted file mode 100644
index a9c430a..0000000
--- a/doc/sphinx/source/api-doc/ufl.corealg.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-ufl.corealg package
-===================
-
-Submodules
-----------
-
-ufl.corealg.map_dag module
---------------------------
-
-.. automodule:: ufl.corealg.map_dag
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.corealg.multifunction module
---------------------------------
-
-.. automodule:: ufl.corealg.multifunction
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.corealg.traversal module
-----------------------------
-
-.. automodule:: ufl.corealg.traversal
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl.corealg
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/api-doc/ufl.finiteelement.rst b/doc/sphinx/source/api-doc/ufl.finiteelement.rst
deleted file mode 100644
index f640e43..0000000
--- a/doc/sphinx/source/api-doc/ufl.finiteelement.rst
+++ /dev/null
@@ -1,118 +0,0 @@
-ufl.finiteelement package
-=========================
-
-Submodules
-----------
-
-ufl.finiteelement.brokenelement module
---------------------------------------
-
-.. automodule:: ufl.finiteelement.brokenelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.elementlist module
-------------------------------------
-
-.. automodule:: ufl.finiteelement.elementlist
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.enrichedelement module
-----------------------------------------
-
-.. automodule:: ufl.finiteelement.enrichedelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.facetelement module
--------------------------------------
-
-.. automodule:: ufl.finiteelement.facetelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.finiteelement module
---------------------------------------
-
-.. automodule:: ufl.finiteelement.finiteelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.finiteelementbase module
-------------------------------------------
-
-.. automodule:: ufl.finiteelement.finiteelementbase
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.hdivcurl module
----------------------------------
-
-.. automodule:: ufl.finiteelement.hdivcurl
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.interiorelement module
-----------------------------------------
-
-.. automodule:: ufl.finiteelement.interiorelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.mixedelement module
--------------------------------------
-
-.. automodule:: ufl.finiteelement.mixedelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.outerproductelement module
---------------------------------------------
-
-.. automodule:: ufl.finiteelement.outerproductelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.restrictedelement module
-------------------------------------------
-
-.. automodule:: ufl.finiteelement.restrictedelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.tensorproductelement module
----------------------------------------------
-
-.. automodule:: ufl.finiteelement.tensorproductelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.finiteelement.traceelement module
--------------------------------------
-
-.. automodule:: ufl.finiteelement.traceelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl.finiteelement
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/api-doc/ufl.formatting.rst b/doc/sphinx/source/api-doc/ufl.formatting.rst
deleted file mode 100644
index 92b496e..0000000
--- a/doc/sphinx/source/api-doc/ufl.formatting.rst
+++ /dev/null
@@ -1,54 +0,0 @@
-ufl.formatting package
-======================
-
-Submodules
-----------
-
-ufl.formatting.graph module
----------------------------
-
-.. automodule:: ufl.formatting.graph
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.formatting.latextools module
---------------------------------
-
-.. automodule:: ufl.formatting.latextools
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.formatting.printing module
-------------------------------
-
-.. automodule:: ufl.formatting.printing
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.formatting.ufl2dot module
------------------------------
-
-.. automodule:: ufl.formatting.ufl2dot
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.formatting.ufl2latex module
--------------------------------
-
-.. automodule:: ufl.formatting.ufl2latex
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl.formatting
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/api-doc/ufl.rst b/doc/sphinx/source/api-doc/ufl.rst
deleted file mode 100644
index 24c0d3b..0000000
--- a/doc/sphinx/source/api-doc/ufl.rst
+++ /dev/null
@@ -1,354 +0,0 @@
-ufl package
-===========
-
-Subpackages
------------
-
-.. toctree::
-
-    ufl.algorithms
-    ufl.core
-    ufl.corealg
-    ufl.finiteelement
-    ufl.formatting
-    ufl.utils
-
-Submodules
-----------
-
-ufl.algebra module
-------------------
-
-.. automodule:: ufl.algebra
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.argument module
--------------------
-
-.. automodule:: ufl.argument
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.assertions module
----------------------
-
-.. automodule:: ufl.assertions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.cell module
----------------
-
-.. automodule:: ufl.cell
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.checks module
------------------
-
-.. automodule:: ufl.checks
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.classes module
-------------------
-
-.. automodule:: ufl.classes
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.coefficient module
-----------------------
-
-.. automodule:: ufl.coefficient
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.compound_expressions module
--------------------------------
-
-.. automodule:: ufl.compound_expressions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.conditional module
-----------------------
-
-.. automodule:: ufl.conditional
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.constantvalue module
-------------------------
-
-.. automodule:: ufl.constantvalue
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.differentiation module
---------------------------
-
-.. automodule:: ufl.differentiation
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.domain module
------------------
-
-.. automodule:: ufl.domain
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.equation module
--------------------
-
-.. automodule:: ufl.equation
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.exprcontainers module
--------------------------
-
-.. automodule:: ufl.exprcontainers
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.exprequals module
----------------------
-
-.. automodule:: ufl.exprequals
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.exproperators module
-------------------------
-
-.. automodule:: ufl.exproperators
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.form module
----------------
-
-.. automodule:: ufl.form
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.formoperators module
-------------------------
-
-.. automodule:: ufl.formoperators
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.functionspace module
-------------------------
-
-.. automodule:: ufl.functionspace
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.geometry module
--------------------
-
-.. automodule:: ufl.geometry
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.index_combination_utils module
-----------------------------------
-
-.. automodule:: ufl.index_combination_utils
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.indexed module
-------------------
-
-.. automodule:: ufl.indexed
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.indexing module
--------------------
-
-.. automodule:: ufl.indexing
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.indexsum module
--------------------
-
-.. automodule:: ufl.indexsum
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.integral module
--------------------
-
-.. automodule:: ufl.integral
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.log module
---------------
-
-.. automodule:: ufl.log
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.mathfunctions module
-------------------------
-
-.. automodule:: ufl.mathfunctions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.measure module
-------------------
-
-.. automodule:: ufl.measure
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.objects module
-------------------
-
-.. automodule:: ufl.objects
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.operators module
---------------------
-
-.. automodule:: ufl.operators
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.permutation module
-----------------------
-
-.. automodule:: ufl.permutation
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.precedence module
----------------------
-
-.. automodule:: ufl.precedence
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.protocols module
---------------------
-
-.. automodule:: ufl.protocols
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.referencevalue module
--------------------------
-
-.. automodule:: ufl.referencevalue
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.restriction module
-----------------------
-
-.. automodule:: ufl.restriction
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.sobolevspace module
------------------------
-
-.. automodule:: ufl.sobolevspace
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.sorting module
-------------------
-
-.. automodule:: ufl.sorting
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.split_functions module
---------------------------
-
-.. automodule:: ufl.split_functions
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.tensoralgebra module
-------------------------
-
-.. automodule:: ufl.tensoralgebra
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.tensors module
-------------------
-
-.. automodule:: ufl.tensors
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.variable module
--------------------
-
-.. automodule:: ufl.variable
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/api-doc/ufl.utils.rst b/doc/sphinx/source/api-doc/ufl.utils.rst
deleted file mode 100644
index 96cb88a..0000000
--- a/doc/sphinx/source/api-doc/ufl.utils.rst
+++ /dev/null
@@ -1,102 +0,0 @@
-ufl.utils package
-=================
-
-Submodules
-----------
-
-ufl.utils.counted module
-------------------------
-
-.. automodule:: ufl.utils.counted
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.derivativetuples module
----------------------------------
-
-.. automodule:: ufl.utils.derivativetuples
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.dicts module
-----------------------
-
-.. automodule:: ufl.utils.dicts
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.formatting module
----------------------------
-
-.. automodule:: ufl.utils.formatting
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.indexflattening module
---------------------------------
-
-.. automodule:: ufl.utils.indexflattening
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.sequences module
---------------------------
-
-.. automodule:: ufl.utils.sequences
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.sorting module
-------------------------
-
-.. automodule:: ufl.utils.sorting
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.stacks module
------------------------
-
-.. automodule:: ufl.utils.stacks
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.system module
------------------------
-
-.. automodule:: ufl.utils.system
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.timer module
-----------------------
-
-.. automodule:: ufl.utils.timer
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-ufl.utils.ufltypedicts module
------------------------------
-
-.. automodule:: ufl.utils.ufltypedicts
-    :members:
-    :undoc-members:
-    :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: ufl.utils
-    :members:
-    :undoc-members:
-    :show-inheritance:
diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py
index d7f3bcc..d662b0e 100644
--- a/doc/sphinx/source/conf.py
+++ b/doc/sphinx/source/conf.py
@@ -53,7 +53,7 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'Unified Form Language (UFL)'
-copyright = u'2015, FEniCS Project'
+copyright = u'2016, FEniCS Project'
 author = u'FEniCS Project'
 
 # The version info for the project you're documenting, acts as replacement for
@@ -290,3 +290,22 @@ texinfo_documents = [
 
 # If true, do not generate a @detailmenu in the "Top" node's menu.
 #texinfo_no_detailmenu = False
+
+
+def run_apidoc(_):
+    modules = ['ufl']
+
+    # Get location of Sphinx files
+    sphinx_source_dir = os.path.abspath(os.path.dirname(__file__))
+    repo_dir = os.path.abspath(os.path.join(sphinx_source_dir, os.path.pardir,
+                                            os.path.pardir, os.path.pardir))
+    apidoc_dir = os.path.join(sphinx_source_dir, "api-doc")
+
+    from sphinx.apidoc import main
+    for module in modules:
+        # Generate .rst files ready for autodoc
+        module_dir = os.path.join(repo_dir, module)
+        main(["-f", "-d", "1", "-o", apidoc_dir, module_dir])
+
+def setup(app):
+    app.connect('builder-inited', run_apidoc)
diff --git a/doc/sphinx/source/index.rst b/doc/sphinx/source/index.rst
index 9e57734..78a4272 100644
--- a/doc/sphinx/source/index.rst
+++ b/doc/sphinx/source/index.rst
@@ -1,110 +1,34 @@
-.. title:: Unified Form Language
+.. title:: UFL
 
-***************************
-Unified Form Language (UFL)
-***************************
 
-This is the documentation for the Unified Form Language from the
-FEniCS Project (http://fenicsproject.org). The Unified Form Language
-(UFL) is a domain specific language for declaration of finite element
-discretizations of variational forms. More precisely, it defines a
-flexible interface for choosing finite element spaces and defining
-expressions for weak forms in a notation close to mathematical
-notation. UFL is described in the paper
+==========================
+UFL: Unified Form Language
+==========================
 
-Alnæs, M. S., Logg A., Ølgaard, K. B., Rognes, M. E. and
-Wells, G. N. (2014). Unified Form Language: A domain-specific language
-for weak formulations of partial differential equations. *ACM
-Transactions on Mathematical Software* 40(2), Article 9, 37
-pages. [http://dx.doi.org/doi:10.1145/2566630>]
-[http://arxiv.org/abs/1211.4047]
+The Unified Form Language (UFL) is a domain specific language for
+declaration of finite element discretizations of variational
+forms. More precisely, it defines a flexible interface for choosing
+finite element spaces and defining expressions for weak forms in a
+notation close to mathematical notation.
 
-UFL is most commonly used as the input language for the FEniCS Form
-Compiler (FFC) and in combination with the problem solving environment
-DOLFIN.
+UFL is part of the FEniCS Project.
 
+For more information, visit http://www.fenicsproject.org
 
 
-Installation
-============
-
-Debian/Ubuntu packages
-----------------------
-
-Debian/Ubuntu
-^^^^^^^^^^^^^
-
-A Debian/Ubuntu package ``python-ufl`` is available for UFL:
-
-    sudo apt-get install python-ufl
-
-
-Ubuntu PPA
-^^^^^^^^^^
-
-UFL is available in the FEniCS Project PPA. The version of UFL
-available in the PPA will generally more recent than the Debian/Ubuntu
-package. To install UFL from the PPA:
-
-    sudo add-apt-repository ppa:fenics-packages/fenics
-    sudo apt-get update
-    sudo apt-get install fenics
-
-
-From source
------------
-
-Dependencies
-^^^^^^^^^^^^
-
-UFL depends on the Python packages ``numpy`` and ``six``, and
-``setuptools`` is recommended. If ``setuptools`` is available, the UFL
-installer will install missing dependencies automatically.
-
-
-Installation
-^^^^^^^^^^^^
-
-The source for UFL releases can be downloaded from
-http://fenicsproject.org/pub/software/ufl/. To install UFL
-system-wide, from the source directory use:
-
-    python setup.py install
-
-To install into a specified directory, use the ``--prefix`` option.
-
-
-Help and support
-================
-
-Send help requests and questions to fenics-support at googlegroups.com.
-
-Send feature requests and questions to fenics-dev at googlegroups.com
-
-
-Development and reporting bugs
-------------------------------
-
-The git source repository for UFL is located at
-https://bitbucket.org/fenics-project/ufl. For general UFL development
-questions and to make feature requests, use
-fenics-dev at googlegroups.com.
-
-Bugs can be registered at
-https://bitbucket.org/fenics-project/ufl/issues.
-
-
-
-Manual and API reference
-========================
+Documentation
+=============
 
 .. toctree::
    :titlesonly:
+   :maxdepth: 1
 
-   User Manual <user/user_manual>
-   API Reference <api-doc/modules>
-   Releases <releases>
+   installation
+   manual
+   API reference <api-doc/ufl>
+   releases
+
+[FIXME: These links don't belong here, should go under API reference somehow.]
 
-* :ref:`modindex`
 * :ref:`genindex`
-* :ref:`search`
+* :ref:`modindex`
diff --git a/doc/sphinx/source/installation.rst b/doc/sphinx/source/installation.rst
new file mode 100644
index 0000000..f01733f
--- /dev/null
+++ b/doc/sphinx/source/installation.rst
@@ -0,0 +1,47 @@
+.. title:: Installation
+
+
+============
+Installation
+============
+
+UFL is normally installed as part of an installation of FEniCS.
+If you are using UFL as part of the FEniCS software suite, it
+is recommended that you follow the
+`installation instructions for FEniCS
+<https://fenics.readthedocs.io/en/latest/>`__.
+
+To install UFL itself, read on below for a list of requirements
+and installation instructions.
+
+
+Requirements and dependencies
+=============================
+
+UFL requires Python version 2.7 or later and depends on the
+following Python packages:
+
+* NumPy
+* six
+
+These packages will be automatically installed as part of the
+installation of UFL, if not already present on your system.
+
+Installation instructions
+=========================
+
+To install UFL, download the source code from the
+`UFL Bitbucket repository
+<https://bitbucket.org/fenics-project/ufl>`__,
+and run the following command:
+
+.. code-block:: console
+
+    pip install .
+
+To install to a specific location, add the ``--prefix`` flag
+to the installation command:
+
+.. code-block:: console
+
+    pip install --prefix=<some directory> .
diff --git a/doc/sphinx/source/manual.rst b/doc/sphinx/source/manual.rst
new file mode 100644
index 0000000..8998494
--- /dev/null
+++ b/doc/sphinx/source/manual.rst
@@ -0,0 +1,16 @@
+.. title:: User manual
+
+
+===========
+User manual
+===========
+
+.. toctree::
+   :maxdepth: 1
+
+   manual/introduction
+   manual/form_language
+   manual/examples
+   manual/internal_representation
+   manual/algorithms
+   manual/command_line_utils
diff --git a/doc/sphinx/source/user/algorithms.rst b/doc/sphinx/source/manual/algorithms.rst
similarity index 75%
rename from doc/sphinx/source/user/algorithms.rst
rename to doc/sphinx/source/manual/algorithms.rst
index a1bf803..637b17e 100644
--- a/doc/sphinx/source/user/algorithms.rst
+++ b/doc/sphinx/source/manual/algorithms.rst
@@ -4,7 +4,9 @@ Algorithms
 
 Algorithms to work with UFL forms and expressions can be found in the
 submodule ``ufl.algorithms``.  You can import all of them with
-the line::
+the line
+
+::
 
   from ufl.algorithms import *
 
@@ -36,7 +38,7 @@ form for the formatting sections below::
 
 str
 ---
-Compact human readable pretty printing.  Useful in interactive Python
+Compact, human readable pretty printing.  Useful in interactive Python
 sessions.  Example output of ``str(a)``::
 
   { v_0 * v_1 * w_0 } * dx(<Mesh #-1 with coordinates parameterized by <Lagrange vector element of degree 1 on a triangle: 2 x <CG1 on a triangle>>>[everywhere], {})
@@ -44,7 +46,7 @@ sessions.  Example output of ``str(a)``::
 
 repr
 ----
-Accurate description of expression, with the property that
+Accurate description of an expression, with the property that
 ``eval(repr(a)) == a``.  Useful to see which representation types
 occur in an expression, especially if ``str(a)`` is ambiguous.
 Example output of ``repr(a)``::
@@ -55,7 +57,7 @@ Example output of ``repr(a)``::
 Tree formatting
 ---------------
 
-Ascii tree formatting, useful to inspect the tree structure of
+ASCII tree formatting, useful to inspect the tree structure of
 an expression in interactive Python sessions.  Example output of
 ``tree_format(a)``::
 
@@ -106,40 +108,49 @@ outputs::
   v_0 * v_1 * w_0
   v_0 * w_1
 
+..
+    ``post_traversal``
+    ^^^^^^^^^^^^^^^^^^^
 
-``post_traversal``
-^^^^^^^^^^^^^^^^^^^
-
-TODO: traversal.py
+..
+    TODO: traversal.py
 
-``pre_traversal``
-^^^^^^^^^^^^^^^^^^
+..
+    ``pre_traversal``
+    ^^^^^^^^^^^^^^^^^^
 
-TODO: traversal.py
+..
+    TODO: traversal.py
 
 
-``walk``
-^^^^^^^^
+..
+    ``walk``
+    ^^^^^^^^
 
-TODO: traversal.py
+..
+    TODO: traversal.py
 
 
-``traverse_terminals``
-^^^^^^^^^^^^^^^^^^^^^^^
+..
+    ``traverse_terminals``
+    ^^^^^^^^^^^^^^^^^^^^^^^
 
-TODO: traversal.py
+..
+    TODO: traversal.py
 
 
-Extracting information
-----------------------
+..
+    Extracting information
+    ----------------------
 
-TODO: analysis.py
+..
+    TODO: analysis.py
 
 
 Transforming expressions
 ------------------------
 
-So far the algorithms presented has been about inspecting expressions
+So far we presented algorithms meant to inspect expressions
 in various ways. Some recurring patterns occur when writing algorithms
 to modify expressions, either to apply mathematical transformations or
 to change their representation. Usually, different expression node types
@@ -208,7 +219,9 @@ Here is a simple example to show how to override default behaviour::
   b = r.visit(a)
   print b
 
-outputs::
+which outputs
+
+::
 
   3.14 * v_0
 
@@ -222,7 +235,7 @@ without recursing into its children, usually applied to terminals.
 To set these defaults with less code, inherit ``ReuseTransformer``
 instead of ``Transformer``. This ensures that the parts of the
 expression tree that are not changed by the transformation algorithms
-always reuse the same instances.
+will always reuse the same instances.
 
 We have already mentioned the difference between pre--traversal
 and post--traversal, and some times you need to combine the
@@ -256,13 +269,13 @@ Here is an example of mixing pre- and post-traversal::
   b = r.visit(a)
   print b
 
-This code inherits the ``ReuseTransformer`` like explained above,
+This code inherits the ``ReuseTransformer`` as explained above,
 so the default behaviour is to recurse into children first and then call
-``Transformer.reuse\_if\_possible`` to reuse or reconstruct each
+``Transformer.reuse_if_possible`` to reuse or reconstruct each
 expression node.  Since ``sum`` only takes ``self`` and the
 expression node instance ``o`` as arguments, its children are not
-visited automatically, and ``sum`` calls on ``self.visit``
-to do this explicitly.
+visited automatically, and ``sum`` explicitly calls ``self.visit``
+to do this.
 
 
 Automatic differentiation implementation
@@ -271,24 +284,92 @@ Automatic differentiation implementation
 This subsection is mostly for form compiler developers and technically
 interested users.
 
-TODO: More details about AD algorithms for developers.
+First of all, we give a brief explanation of the algorithm.
+Recall that a ``Coefficient`` represents a
+sum of unknown coefficients multiplied with unknown
+basis functions in some finite element space.
+
+.. math::
+
+   w(x) = \sum_k w_k \phi_k(x)
+
+Also recall that an ``Argument`` represents any (unknown) basis
+function in some finite element space.
+
+.. math::
+
+   v(x) = \phi_k(x), \qquad \phi_k \in V_h .
+
+A form :math:`L(v; w)` implemented in UFL is intended for discretization
+like
+
+.. math::
+
+   b_i = L(\phi_i; \sum_k w_k \phi_k), \qquad \forall \phi_i \in V_h .
+
+The Jacobi matrix :math:`A_{ij}` of this vector can be obtained by
+differentiation of :math:`b_i` w.r.t. :math:`w_j`, which can be written
+
+.. math::
+
+   A_{ij} = \frac{d b_i}{d w_j} = a(\phi_i, \phi_j; \sum_k w_k \phi_k), \qquad \forall \phi_i \in V_h, \quad \forall \phi_j \in V_h ,
+
+for some form `a`. In UFL, the form `a` can be obtained by
+differentiating `L`.  To manage this, we note that as long as the domain
+:math:`\Omega` is independent of :math:`w_j`, :math:`\int_\Omega` commutes with :math:`\frac{d}{d
+w_j}`, and we can differentiate the integrand expression instead, e.g.,
 
+.. math::
+
+   L(v; w) = \int_\Omega I_c(v; w) \, dx + \int_{\partial\Omega} I_e(v; w) \, ds, \\
+      \frac{d}{d w_j} L(v; w) = \int_\Omega \frac{d I_c}{d w_j} \, dx + \int_{\partial\Omega} \frac{d I_e}{d w_j} \, ds.
+
+In addition, we need that
+
+.. math::
+
+   \frac{d w}{d w_j} = \phi_j, \qquad \forall \phi_j \in V_h ,
+
+which in UFL can be represented as
+
+.. math::
+
+   w &= \mathtt{Coefficient(element)}, \\
+   v &= \mathtt{Argument(element)}, \\
+   \frac{dw}{d w_j} &= v,
+
+since :math:`w` represents the sum and :math:`v` represents any and all
+basis functions in :math:`V_h`.
 
-Forward mode
-------------
+Other operators have well defined derivatives, and by repeatedly applying
+the chain rule we can differentiate the integrand automatically.
 
-TODO: forward_ad.py
 
+..
+    TODO: More details about AD algorithms for developers.
 
-Reverse mode
-------------
 
-TODO: reverse_ad.py
+..
+    Forward mode
+    ------------
 
-Mixed derivatives
------------------
+..
+    TODO: forward_ad.py
 
-TODO: ad.py
+
+..
+    Reverse mode
+    ------------
+
+..
+    TODO: reverse_ad.py
+
+..
+    Mixed derivatives
+    -----------------
+
+..
+    TODO: ad.py
 
 
 Computational graphs
@@ -299,26 +380,26 @@ interest to end-users.
 
 An expression tree can be seen as a directed acyclic graph (DAG).
 To aid in the implementation of form compilers, UFL includes tools to
-build a linearized\footnote{Linearized as in a linear datastructure,
-do not confuse this with automatic differentiation.} computational graph
-from the abstract expression tree.
+build a linearized [#]_ computational graph from the abstract expression tree.
 
 A graph can be partitioned into subgraphs based on dependencies of
 subexpressions, such that a quadrature based compiler can easily place
 subexpressions inside the right sets of loops.
 
-% TODO: Finish and test this before writing about it :)
-%The vertices of a graph can be reordered to improve the efficiency
-%of the generated code, an operation usually called operation scheduling.
+.. [#] Linearized as in a linear datastructure,
+   do not confuse this with automatic differentiation.
+
+..
+    TODO: Finish and test this before writing about it :)
+    The vertices of a graph can be reordered to improve the efficiency
+    of the generated code, an operation usually called operation scheduling.
 
 The computational graph
 -----------------------
+..
+    TODO: finish graph.py:
 
-TODO: finish graph.py:
-
-  TODO
-
-Consider the expression:
+Consider the expression
 
 .. math::
 
@@ -333,7 +414,7 @@ The *expression tree* for f looks like this::
       \     /
          *
 
-In UFL f is represented like this expression tree.  If a,b,c,d are all
+In UFL f is represented like this expression tree.  If a, b, c, d are all
 distinct Coefficient instances, the UFL representation will look like this::
 
   Coefficient Coefficient Coefficient Coefficient
@@ -365,15 +446,17 @@ two vertices, i.e. that one vertex is among the operands of another.
 A graph can also be represented in a linearized data structure, consisting
 of an array of vertices and an array of edges. This representation is
 convenient for many algorithms. An example to illustrate this graph
-representation::
+representation follows::
 
   G = V, E
   V = [a, b, a+b, c, d, c+d, (a+b)*(c+d)]
   E = [(6,2), (6,5), (5,3), (5,4), (2,0), (2,1)]
 
-In the following this representation of an expression will be called
+In the following, this representation of an expression will be called
 the *computational graph*.  To construct this graph from a UFL
-expression, simply do::
+expression, simply do
+
+::
 
   G = Graph(expression)
   V, E = G
@@ -412,6 +495,11 @@ Partitioning the graph
 To help generate better code efficiently, we can partition vertices by
 their dependencies, which allows us to, e.g., place expressions outside
 the quadrature loop if they don't depend (directly or indirectly) on
-the spatial coordinates. This is done simply by::
+the spatial coordinates. This is done simply by
+
+..
+    TODO
+
+::
 
-  P = partition(G) # TODO
+  P = partition(G)
diff --git a/doc/sphinx/source/user/command_line_utils.rst b/doc/sphinx/source/manual/command_line_utils.rst
similarity index 78%
rename from doc/sphinx/source/user/command_line_utils.rst
rename to doc/sphinx/source/manual/command_line_utils.rst
index ea02ce1..94e499f 100644
--- a/doc/sphinx/source/user/command_line_utils.rst
+++ b/doc/sphinx/source/manual/command_line_utils.rst
@@ -2,20 +2,39 @@
 Commandline utilities
 *********************
 
+See installed version: ``ufl-analyse``
+======================================
+
+Run
+
+::
+
+   # ufl-version
+
+to see the currently installed version of UFL printed to the terminal.
+
 
 Validation and debugging: ``ufl-analyse``
 =========================================
 
 The command ``ufl-analyse`` loads all forms found in a ``.ufl``
 file, tries to discover any errors in them, and prints various kinds of
-information about each form.  Basic usage is::
+information about each form.  Basic usage is
+
+::
 
   # ufl-analyse myform.ufl
 
-For more information, type::
+For more information, type
+
+::
 
   # ufl-analyse --help
 
+Note: This script is not well maintained, you will likely get more
+useful information from your form compiler.
+
+
 Formatting and visualization: ``ufl-convert``
 =============================================
 
diff --git a/doc/sphinx/source/user/examples.rst b/doc/sphinx/source/manual/examples.rst
similarity index 88%
rename from doc/sphinx/source/user/examples.rst
rename to doc/sphinx/source/manual/examples.rst
index c9fd8f7..448481a 100644
--- a/doc/sphinx/source/user/examples.rst
+++ b/doc/sphinx/source/manual/examples.rst
@@ -202,8 +202,8 @@ obtain the following variational problem for the discrete solution :math:`u_h
    \int_{\Omega} c \, \nabla v \cdot \nabla u_h^n \mathop{dx} =
    \int_{\Omega} v \, f^n \mathop{dx}
 
-for all test functions :math:`v`, where :math:`k = t_n - t_{n-1}`
-denotes the time step . In the example below, we implement this
+for all test functions :math:`v`, where :math:`k_n = t_n - t_{n-1}`
+denotes the time step. In the example below, we implement this
 variational problem with piecewise linear test and trial functions,
 but other choices are possible (just choose another finite element).
 
@@ -279,15 +279,15 @@ Mixed formulation of Poisson
 
 We next consider the following formulation of Poisson's equation as a
 pair of first order equations for :math:`\sigma \in H(\mathrm{div})`
-and :math:`u \in L_2`:
+and :math:`u \in L^2`:
 
 .. math::
    \sigma + \nabla u &= 0, \\
    \nabla \cdot \sigma &= f.
 
-We multiply the two equations by a pair of test functions $\tau$ and
-$w$ and integrate by parts to obtain the following variational
-problem: Find $(\sigma, u) \in V = H(\mathrm{div}) \times L_2$ such that
+We multiply the two equations by a pair of test functions :math:`\tau` and
+:math:`w` and integrate by parts to obtain the following variational
+problem: Find :math:`(\sigma, u) \in V = H(\mathrm{div}) \times L^2` such that
 
 .. math::
 
@@ -304,8 +304,8 @@ where
 
 We may implement the corresponding forms in our form language using
 first order BDM H(div)-conforming elements for
-:math:\sigma and piecewise constant :math`L_2`-conforming elements for
-:math:u as follows::
+:math:`\sigma` and piecewise constant :math:`L^2`-conforming elements for
+:math:`u` as follows::
 
   cell = triangle
   BDM1 = FiniteElement("Brezzi-Douglas-Marini", cell, 1)
@@ -329,7 +329,7 @@ Poisson equation with DG elements
 =================================
 
 We consider again Poisson's equation, but now in an (interior penalty)
-discontinuous Galerkin formulation: Find :math:`u \in V = L_2` such that
+discontinuous Galerkin formulation: Find :math:`u \in V = L^2` such that
 
 .. math::
 
@@ -360,10 +360,9 @@ first order elements may be implemented as follows::
 
   f = Coefficient(DG1)
   g = Coefficient(DG1)
-  #h = MeshSize(cell) # TODO: Do we include MeshSize in UFL?
-  h = Constant(cell)
-  alpha = 1 # TODO: Set to proper value
-  gamma = 1 # TODO: Set to proper value
+  h = 2.0*Circumradius(cell)
+  alpha = 1
+  gamma = 1
 
   a = dot(grad(v), grad(u))*dx \
     - dot(avg(grad(v)), jump(u))*dS \
@@ -374,32 +373,36 @@ first order elements may be implemented as follows::
     + gamma/h*v*u*ds
   L = v*f*dx + v*g*ds
 
+..
+    TODO: set alpha and gamma to proper values
+
 This example is implemented in the file ``PoissonDG.ufl`` in
 the collection of demonstration forms included with the UFL source
 distribution.
 
 
-Quadrature elements
-===================
+The Quadrature family
+=====================
 
-*FIXME: The code examples in this section have been mostly converted
-to UFL syntax, but the quadrature elements need some more updating, as
-well as the text.  In UFL, I think we should define the element order
-and not the number of points for quadrature elements, and let the form
-compiler choose a quadrature rule.  This way the form depends less on
-the cell in use.*
+..
+    *FIXME: The code examples in this section have been mostly converted
+    to UFL syntax, but the quadrature elements need some more updating, as
+    well as the text.  In UFL, I think we should define the element order
+    and not the number of points for quadrature elements, and let the form
+    compiler choose a quadrature rule.  This way the form depends less on
+    the cell in use.*
 
 We consider here a nonlinear version of the Poisson's equation to
 illustrate the main point of the ``Quadrature`` finite element
 family. The strong equation looks as follows:
 
-.. math:
+.. math::
 
   - \nabla \cdot (1+u^2)\nabla u = f.
 
 The linearised bilinear and linear forms for this equation,
 
-.. math:
+.. math::
 
    a(v, u; u_0) &= \int_{\Omega} (1+u_{0}^2) \nabla v \cdot \nabla u \mathop{dx}
    + \int_{\Omega} 2u_0 u \nabla v \cdot \nabla u_0 \mathop{dx},
@@ -422,15 +425,15 @@ can be implemented in a single form file as follows::
 Here, :math:`u_0` represents the solution from the previous Newton-Raphson
 iteration.
 
-The above form will be denoted REF1 and serve as our reference
+The above form will be denoted REF1 and serves as our reference
 implementation for linear elements. A similar form (REF2) using quadratic
 elements will serve as a reference for quadratic elements.
 
 Now, assume that we want to treat the quantities :math:`C = (1 + u_{0}^2)`
 and :math:`\sigma_0 = (1+u_{0}^2) \nabla u_0` as given functions (to be
-computed elsewhere). Substituting into bilinear linear forms, we obtain
+computed elsewhere). Substituting into the bilinear and linear forms, we obtain
 
-.. math:
+.. math::
    a(v, u) &= \int_{\Omega} \text{C} \nabla v \cdot \nabla u \mathop{dx}
    + \int_{\Omega} 2u_0 u \nabla v \cdot \nabla u_0 \mathop{dx},
    \\
@@ -441,8 +444,11 @@ Then, two additional forms are created to compute the tangent C and
 the gradient of :math:`u_0`. This situation shows up in plasticity and
 other problems where certain quantities need to be computed elsewhere
 (in user-defined functions).  The three forms using the standard
-``FiniteElement`` (linear elements) can then be implemented as::
+``FiniteElement`` (linear elements) can then be implemented as
 
+::
+
+  # NonlinearPoisson.ufl
   element = FiniteElement("Lagrange", triangle, 1)
   DG = FiniteElement("Discontinuous Lagrange", triangle, 0)
   sig = VectorElement("Discontinuous Lagrange", triangle, 0)
@@ -457,8 +463,11 @@ other problems where certain quantities need to be computed elsewhere
   a = v.dx(i)*C*u.dx(i)*dx + v.dx(i)*2*u0*u*u0.dx(i)*dx
   L = v*f*dx - dot(grad(v), sig0)*dx
 
-and::
+and
+
+::
 
+  # Tangent.ufl
   element = FiniteElement("Lagrange", triangle, 1)
   DG = FiniteElement("Discontinuous Lagrange", triangle, 0)
 
@@ -469,8 +478,11 @@ and::
   a = v*u*dx
   L = v*(1.0 + u0**2)*dx
 
-and::
+and
+
+::
 
+  # Gradient.ufl
   element = FiniteElement("Lagrange", triangle, 1)
   DG = VectorElement("Discontinuous Lagrange", triangle, 0)
 
@@ -479,7 +491,7 @@ and::
   u0 = Coefficient(element)
 
   a = dot(v, u)*dx
-  L = dot(v, grad(u0))*dx
+  L = dot(v, (1.0 + u0**2)*grad(u0))*dx
 
 The three forms can be implemented using the ``QuadratureElement``
 in a similar fashion in which only the element declaration is different::
@@ -489,27 +501,31 @@ in a similar fashion in which only the element declaration is different::
   QE = FiniteElement("Quadrature", triangle, 2)
   sig = VectorElement("Quadrature", triangle, 2)
 
-and::
+and
+
+::
 
   # QE1Tangent.ufl
   element = FiniteElement("Lagrange", triangle, 1)
   QE = FiniteElement("Quadrature", triangle, 2)
 
-and::
+and
+
+::
 
   # QE1Gradient.ufl
   element = FiniteElement("Lagrange", triangle, 1)
   QE = VectorElement("Quadrature", triangle, 2)
 
 Note that we use two points when declaring the ``QuadratureElement``. This
-is because the RHS of the ``Tangent.form`` is second order and therefore
+is because the RHS of ``Tangent.form`` is second order and therefore
 we need two points for exact integration. Due to consistency issues,
 when passing functions around between the forms, we also need to use
 two points when declaring the ``QuadratureElement`` in the other forms.
 
 Typical values of the relative residual for each Newton iteration for all
-three approaches are shown in Table~\ref{tab:convergence1}. It is noted
-that the convergence rate is quadratic as it should be for all 3 methods.
+three approaches are shown in the table below. It is to be noted
+that the convergence rate is quadratic as it should be for all three methods.
 
 Relative residuals for each approach for linear elements::
 
@@ -520,9 +536,9 @@ Relative residuals for each approach for linear elements::
   3         3.7e-08   3.7e-08  3.7e-08
   4         2.9e-16   2.9e-16  2.5e-16
 
-However, if quadratic elements are used to interpolate the unknown field u,
+However, if quadratic elements are used to interpolate the unknown field :math:`u`,
 the order of all elements in the above forms is increased by 1. This influences
-the convergence rate as seen in Table (tab:convergence2). Clearly, using
+the convergence rate as seen in the table below. Clearly, using
 the standard ``FiniteElement`` leads to a poor convergence whereas
 the ``QuadratureElement`` still leads to quadratic convergence.
 
@@ -542,4 +558,5 @@ More examples
 Feel free to send additional demo form files for your favourite PDE to
 the UFL mailing list.
 
-%TODO: Modify rest of FFC example forms to UFL syntax and add here.
+..
+    %TODO: Modify rest of FFC example forms to UFL syntax and add here.
diff --git a/doc/sphinx/source/user/form_language.rst b/doc/sphinx/source/manual/form_language.rst
similarity index 89%
rename from doc/sphinx/source/user/form_language.rst
rename to doc/sphinx/source/manual/form_language.rst
index 2f1418f..36f024a 100644
--- a/doc/sphinx/source/user/form_language.rst
+++ b/doc/sphinx/source/manual/form_language.rst
@@ -8,12 +8,13 @@ all these operators and atomic expressions in detail.
 
 UFL is built on top of the Python language, and any Python code is
 valid in the definition of a form.
-In particular, comments (lines starting with ``#`` and functions (keyword ``def``, see _user-defined
+In particular, comments (lines starting with ``#``) and functions
+(keyword ``def``, see user-defined_
 below) are useful in the definition of a form.  However, it is usually a
 good idea to avoid using advanced Python features in the form definition,
 to stay close to the mathematical notation.
 
-The entire form language can be imported in Python with the line:
+The entire form language can be imported in Python with the line
 
 .. code-block:: python
 
@@ -48,7 +49,7 @@ to define form arguments and integrand expressions is detailed in the
 rest of this chapter.
 
 Integrals are expressed through multiplication with a measure,
-representing an integral over either of:
+representing an integral over either
 
     * the interior of the domain :math:`\Omega` (``dx``, cell integral);
 
@@ -56,7 +57,7 @@ representing an integral over either of:
 
     * the set of interior facets :math:`\Gamma` (``dS``, interior facet integral).
 
-(Note that newer versions of UFL supports several other integral
+(Note that newer versions of UFL support several other integral
 types currently not documented here).
 As a basic example, assume ``v`` is a scalar-valued expression and
 consider the integral of ``v`` over the interior of :math:`\Omega`. This
@@ -66,10 +67,10 @@ may be expressed as::
 
 and the integral of ``v`` over :math:`\partial\Omega` is written as::
 
-  a = v*ds
+  a = v*ds.
 
 Alternatively, measures can be redefined to represent numbered subsets of
-a domain, such that a form can take on different expressions on different
+a domain, such that a form evaluates to different expressions on different
 parts of the domain.  If ``c``, ``e0`` and ``e1`` are scalar-valued
 expressions, then::
 
@@ -79,7 +80,7 @@ represents
 
 .. math::
 
-   a = \int_\Omega c\,dx + \int_{\partial\Omega_0} e_0 \, ds + \int_{\partial\Omega_1} e_1 \, ds.
+   a = \int_\Omega c\,dx + \int_{\partial\Omega_0} e_0 \, ds + \int_{\partial\Omega_1} e_1 \, ds,
 
 where
 
@@ -130,10 +131,10 @@ Objects for regular cells of all basic shapes are predefined::
   cell = hexahedron
 
 In the rest of this document, a variable name ``cell`` will be used where
-any cell is a valid argument, to make the examples dimension independent
+any cell is a valid argument, to make the examples dimension-independent
 wherever possible.  Using a variable ``cell`` to hold the cell type used
 in a form is highly recommended, since this makes most form definitions
-dimension independent.
+dimension-independent.
 
 
 Element families
@@ -141,7 +142,7 @@ Element families
 
 UFL predefines a set of names of known element families.  When defining
 a finite element below, the argument ``family`` is a string and its
-possible values include:
+possible values include
 
 * ``"Lagrange"`` or ``"CG"``, representing standard scalar
   Lagrange finite elements (continuous piecewise polynomial functions);
@@ -178,12 +179,15 @@ possible values include:
   representing vector-valued Nedelec H(curl) elements
   (of the second kind).
 
-* ``"Quadrature"`` or ``"Q"``, representing artificial ``finite elements``
-  with degrees of freedom being function evaluation at quadrature points;
+* ``"Bubble"``,
+  representing bubble elements, useful for example to build the mini elements.
+
+* ``"Quadrature"`` or ``"Q"``, representing artificial "finite elements"
+  with degrees of freedom being function evaluations at quadrature points;
 
 * ``"Boundary Quadrature"`` or ``"BQ"``, representing artificial
-  "finite elements" with degrees of freedom being function evaluation
-  at quadrature points on the boundary;
+  "finite elements" with degrees of freedom being function evaluations
+  at quadrature points on the boundary.
 
 Note that new versions of UFL also support notation from the Periodic Table
 of Finite Elements, currently not documented here.
@@ -193,9 +197,11 @@ Basic elements
 --------------
 
 A ``FiniteElement``, sometimes called a basic element, represents a
-finite element in some family on a given cell with a certain polynomial
+finite element from some family on a given cell with a certain polynomial
 degree. Valid families and cells are explained above.
-The notation is::
+The notation is
+
+::
 
   element = FiniteElement(family, cell, degree)
 
@@ -212,7 +218,9 @@ Vector elements
 A ``VectorElement`` represents a combination of basic elements such that
 each component of a vector is represented by the basic element. The size
 is usually omitted, the default size equals the geometry dimension.
-The notation is::
+The notation is
+
+::
 
   element = VectorElement(family, cell, degree[, size])
 
@@ -231,8 +239,10 @@ Tensor elements
 
 A ``TensorElement`` represents a combination of basic elements such that
 each component of a tensor is represented by the basic element. The
-shape is usually omitted, the default shape is (d, d) where d is the
-geometry dimension. The notation is::
+shape is usually omitted, the default shape is :math: `(d, d)` where :math: `d`
+is the geometric dimension. The notation is
+
+::
 
   element = TensorElement(family, cell, degree[, shape, symmetry])
 
@@ -276,7 +286,7 @@ Shorthand notation for two subelements::
     sub-elements ``(e1 * e2)`` and ``e3``.
 
 See `Form arguments`_ for details on how defining
-functions on mixed spaces can differ from functions on other
+functions on mixed spaces can differ from defining functions on other
 finite element spaces.
 
 Examples::
@@ -298,7 +308,9 @@ EnrichedElement
 The data type ``EnrichedElement`` represents the vector sum of two
 (or more) finite elements.
 
-Example: The Mini element can be constructed as::
+Example: The Mini element can be constructed as
+
+::
 
   P1 = VectorElement("Lagrange", "triangle", 1)
   B  = VectorElement("Bubble", "triangle", 3)
@@ -345,7 +357,7 @@ Taylor--Hood element::
   vq = Argument(TH)
   v, q = split(up)
 
-A shorthand for this is in place called ``Arguments``::
+This is equivalent to the previous use of ``Arguments``::
 
   v, q = Arguments(TH)
 
@@ -407,9 +419,10 @@ values on subspaces, as illustrated here for a mixed Taylor--Hood element::
   up = Coefficient(TH)
   u, p = split(up)
 
-A shorthand for this is in place called ``Coefficients``::
+There is a shorthand for this, whose use is similar to ``Arguments``, called
+``Coefficients``::
 
-  u, p = Coefficient(TH)
+  u, p = Coefficients(TH)
 
 Spatially constant (or discontinuous piecewise constant) functions can
 conveniently be represented by ``Constant``, ``VectorConstant``, and
@@ -482,7 +495,7 @@ UFL supports index notation, which is often a convenient way to
 express forms. The basic principle of index notation is that summation
 is implicit over indices repeated twice in each term of an expression.
 The following examples illustrate the index notation, assuming that
-each of the variables ``i`` and ``j`` have been declared as
+each of the variables ``i`` and ``j`` has been declared as
 a free ``Index``:
 
 * ``v[i]*w[i]``: :math:`\sum_{i=0}^{n-1} v_i w_i = \mathbf{v}\cdot\mathbf{w}`
@@ -502,7 +515,7 @@ Here we will try to very briefly summarize the basic concepts of tensor
 algebra and index notation, just enough to express the operators in UFL.
 
 Assuming an Euclidean space in :math:`d` dimensions with :math:`1 \le
-d 3`, and a set of orthonormal basis vectors :math:`\mathbf{i}_i` for :math:`i
+d \le 3`, and a set of orthonormal basis vectors :math:`\mathbf{i}_i` for :math:`i
 \in {0, \ldots, d-1 }`, we can define the dot product of any two basis
 functions as
 
@@ -558,7 +571,7 @@ and we can't always interpret such conventions unambiguously.  Therefore,
 UFL requires that an expression is explicitly mapped from its tensor
 representation (:math:`\mathbf{v}`, :math:`\mathbf{A}`) to its component
 representation (:math:`v_i`, :math:`A_{ij}`) and back.  This is done using
-``Index`` objects, the indexing operator (``v[i]``), and the function
+``Index`` objects, the indexing operator (``v[i]``) and the function
 ``as_tensor``.  More details on these follow.
 
 In the following descriptions of UFL operator syntax, i-l and p-s are
@@ -577,7 +590,7 @@ conserve space.
 
 The data type ``Index`` represents an index used for subscripting
 derivatives or taking components of non-scalar expressions.
-To create indices, you can either make a single using ``Index()``
+To create indices you can either make a single one using ``Index()``
 or make several at once conveniently using ``indices(n)``::
 
   i = Index()
@@ -648,7 +661,7 @@ More advanced indexing:
   the last axis fixed, e.g., A[...,0] == A[:,0]
 
 * ``C[j,...]``: subtensor access, representing the subtensor of A with
-  the last axis fixed, e.g., A[j,...] == A[j,:]
+  the first axis fixed, e.g., A[j,...] == A[j,:]
 
 
 Making tensors from components
@@ -660,7 +673,7 @@ single expression with free indices that should map to tensor axes,
 like mapping :math:`v_k` to :math:`\mathbf{v}` or :math:`A_{ij}` to
 :math:`\mathbf{A}`, the following examples show how this is done::
 
-  vk = Identity(cell.d)[0,k]
+  vk = Identity(cell.geometric_dimension())[0,k]
   v = as_tensor(vk, (k,))
 
   Aij = v[i]*u[j]
@@ -709,7 +722,7 @@ treated as a sum over that free index:
 The spatial derivative, in the direction of a free index, of an expression
 with the same free index, is treated as a sum over that free index:
 
-* ``v[i].dx(i)``: :math:`\sum_i v_i`
+* ``v[i].dx(i)``: :math:`\sum_i \frac{d(v_{i})}{dx_i}`
 * ``A[i,j].dx(i)``: :math:`\sum_i \frac{d(A_{ij})}{dx_i}`
 
 Note that these examples are some times written :math:`v_{i,i}` and
@@ -725,17 +738,17 @@ operands, summarized here:
 
 Addition or subtraction, ``a + b`` or ``a - b``:
 
-* The operands a and b must have the same shape.
-* The operands a and b must have the same set of free indices.
+* The operands ``a`` and ``b`` must have the same shape.
+* The operands ``a`` and ``b`` must have the same set of free indices.
 
 Division, ``a / b``:
 
-* The operand b must be a scalar expression.
+* The operand ``b`` must be a scalar expression.
 
-* The operand b must have no free indices.
+* The operand ``b`` must have no free indices.
 
-* The operand a can be non-scalar with free indices, in which division
-  represents scalar division of all components with the scalar b.
+* The operand ``a`` can be non-scalar with free indices, in which division
+  represents scalar division of all components with the scalar ``b``.
 
 Multiplication, ``a * b``:
 
@@ -894,7 +907,7 @@ An example with a vector and a tensor of rank two
 This is the same as a vector-matrix multiplication.
 
 This generalizes to tensors of arbitrary rank:
-The dot product applies to the last axis of a and the first axis of b.
+the dot product applies to the last axis of a and the first axis of b.
 The tensor rank of the product is rank(a)+rank(b)-2.
 
 ``inner``
@@ -954,10 +967,10 @@ Some examples with vectors and matrices are easier to understand:
 .. math::
 
    \mathbf{v} \otimes \mathbf{u} = v_i u_j \mathbf{i}_i \mathbf{i}_j, \\
-   \mathbf{v} \otimes \mathbf{v} = v_i B_{kl} \mathbf{i}_i \mathbf{i}_k \mathbf{i}_l, \\
+   \mathbf{v} \otimes \mathbf{B} = v_i B_{kl} \mathbf{i}_i \mathbf{i}_k \mathbf{i}_l, \\
    \mathbf{A} \otimes \mathbf{B} = A_{ij} B_{kl} \mathbf{i}_i \mathbf{i}_j \mathbf{i}_k \mathbf{i}_l .
 
-The outer product of vectors is often written simply as:
+The outer product of vectors is often written simply as
 
 .. math::
 
@@ -984,21 +997,35 @@ Note that this operator is only defined for vectors of length three.
 ``det``
 -------
 
-The determinant of a matrix A can be written::
+The determinant of a matrix A can be written as
+
+::
 
   d = det(A)
 
 ``dev``
 -------
 
-The deviatoric part of matrix A can be written::
+The deviatoric part of matrix A can be written as
+
+::
 
   B = dev(A)
 
+The definition is
+
+.. math::
+
+  {\rm dev} \mathbf{A} = \mathbf{A} - \frac{\mathbf{A}_{ii}}{d} \mathbf{I}
+
+where :math:`d` is the rank of matrix A and :math:`\mathbf{I}` is the identity matrix.
+
 ``sym``
 -------
 
-The symmetric part of A can be written::
+The symmetric part of A can be written as
+
+::
 
   B = sym(A)
 
@@ -1011,7 +1038,9 @@ The definition is
 ``skew``
 --------
 
-The skew symmetric part of A can be written::
+The skew symmetric part of A can be written as
+
+::
 
   B = skew(A)
 
@@ -1025,7 +1054,9 @@ The definition is
 ``cofac``
 ---------
 
-The cofactor of a matrix A can be written::
+The cofactor of a matrix A can be written as
+
+::
 
   B = cofac(A)
 
@@ -1042,7 +1073,9 @@ symbolic expression for the cofactor.  Therefore, this is limited to 1x1,
 ``inv``
 -------
 
-The inverse of matrix A can be written::
+The inverse of matrix A can be written as
+
+::
 
   Ainv = inv(A)
 
@@ -1073,7 +1106,7 @@ and there are several ways to express those. The basic way is::
   g = v.dx(i)
 
 If ``v`` is a scalar expression, ``f`` here is the scalar derivative of
-``v`` with respect to spatial direction z.  If ``v`` has no free indices, ``g``
+``v`` with respect to spatial direction :math:`z`.  If ``v`` has no free indices, ``g``
 is the scalar derivative in spatial direction :math:`x_i`, and ``g``
 has the free index ``i``.  This can be expressed compactly as :math:`v_{,i}`:
 
@@ -1133,7 +1166,7 @@ The gradient of a vector :math:`\mathbf{v}` is defined as
    \mathrm{grad}(\mathbf{v}) \equiv \nabla \mathbf{v}
    = \frac{\partial v_i}{\partial x_j} \mathbf{i}_i \mathbf{i}_j,
 
-which written componentwise is
+which, written componentwise, reads
 
 .. math::
 
@@ -1149,7 +1182,7 @@ In general for a tensor :math:`\mathbf{A}` of rank :math:`r` the definition is
    = \frac{\partial A_\iota}{\partial x_i} \mathbf{i}_{\iota_0}
    \otimes \cdots \otimes \mathbf{i}_{\iota_{r-1}} \otimes \mathbf{i}_i,
 
-where :math:`\iota` is a multiindex of length :math:`r`.
+where :math:`\iota` is a multi-index of length :math:`r`.
 
 In UFL, the following pairs of declarations are equivalent::
 
@@ -1193,7 +1226,7 @@ Curl and rot
 ------------
 
 The operator ``curl`` or ``rot`` accepts as argument a vector-valued expression
-and returns its curl:
+and returns its curl
 
 .. math::
 
@@ -1229,10 +1262,10 @@ The notation is illustrated here::
   w = variable(w)
 
   # This expression is a function of w
-  F = I + diff(u, x)
+  F = w**2
 
-  # The derivative of expression f w.r.t. the variable w
-  df = diff(f, w)
+  # The derivative of expression F w.r.t. the variable w
+  dF = diff(F, w)  # == 2*w
 
 Note that the variable ``w`` still represents the same expression.
 
@@ -1270,7 +1303,7 @@ Restriction: ``v('+')`` and ``v('-')``
 When integrating over interior facets (``*dS``), one may restrict
 expressions to the positive or negative side of the facet::
 
-  element = FiniteElement("Discontinuous Lagrange", "tetrahedron", 0)
+  element = FiniteElement("Discontinuous Lagrange", tetrahedron, 0)
 
   v = TestFunction(element)
   u = TrialFunction(element)
@@ -1363,7 +1396,7 @@ Conditions
 .. note::
 
   Because of details in the way Python behaves, we cannot overload
-  the == operator hence these named operators.
+  the == operator, hence these named operators.
 
 .. _user-defined:
 
@@ -1402,7 +1435,7 @@ Replacing arguments of a Form
 -----------------------------
 
 The function ``replace`` lets you replace terminal objects with
-other values, using a mapping defined by a Python dict. This can be
+other values, using a mapping defined by a Python dicaionaryt. This can be
 used for example to replace a ``Coefficient`` with a fixed value for
 optimized runtime evaluation.
 
@@ -1494,7 +1527,7 @@ functions in a ``Form``, and is used like this::
 Linear and bilinear parts of a form
 -----------------------------------
 
-Some times it is useful to write an equation on the format
+Sometimes it is useful to write an equation on the format
 
 .. math::
 
@@ -1502,7 +1535,7 @@ Some times it is useful to write an equation on the format
 
 Before assembly, we need to extract the forms corresponding to the left
 hand side and right hand side. This corresponds to extracting the bilinear and linear
-terms of the form respectively, or the terms that depend on both a test
+terms of the form respectively, or separating the terms that depend on both a test
 and a trial function on one side and the terms that depend on only a
 test function on the other.
 
@@ -1512,7 +1545,9 @@ This is easily done in UFL using ``lhs`` and ``rhs``::
   a, L = lhs(b), rhs(b)
 
 Note that ``rhs`` multiplies the extracted terms by -1,
-corresponding to moving them from left to right, so this is equivalent to::
+corresponding to moving them from left to right, so this is equivalent to
+
+::
 
   a = u*v*dx
   L = f*v*dx
@@ -1522,7 +1557,9 @@ As a slightly more complicated example, this formulation::
   F = v*(u - w)*dx + k*dot(grad(v), grad(0.5*(w + u)))*dx
   a, L = lhs(F), rhs(F)
 
-is equivalent to::
+is equivalent to
+
+::
 
   a = v*u*dx + k*dot(grad(v), 0.5*grad(u))*dx
   L = v*w*dx - k*dot(grad(v), 0.5*grad(w))*dx
@@ -1556,40 +1593,52 @@ corresponding to its Jacobi matrix.
    J(v, u; w) = \frac{d}{dw} F(v; w).
 
 The UFL code to express this is (for a simple functional
-:math:`f(w)=\int_\Omega \frac 1 2 w^2\,dx`)::
+:math:`f(w)=\int_\Omega \frac 1 2 w^2\,dx`)
+
+::
 
   f = (w**2)/2 * dx
   F = derivative(f, w, v)
   J = derivative(F, w, u)
 
-which is equivalent to::
+which is equivalent to
+
+::
 
   f = (w**2)/2 * dx
   F = w*v*dx
   J = u*v*dx
 
-Assume in the following examples that::
+Assume in the following examples that
+
+::
 
   v = TestFunction(element)
   u = TrialFunction(element)
   w = Coefficient(element)
 
 The stiffness matrix can be computed from the functional
-:math:`\int_\Omega \nabla w : \nabla w \, dx`, by::
+:math:`\int_\Omega \nabla w : \nabla w \, dx`, by
+                              
+::
 
   f = inner(grad(w), grad(w))/2 * dx
   F = derivative(f, w, v)
   J = derivative(F, w, u)
 
-which is equivalent to::
+which is equivalent to
+
+::
 
   f = inner(grad(w), grad(w))/2 * dx
   F = inner(grad(w), grad(v)) * dx
   J = inner(grad(u), grad(v)) * dx
 
 Note that here the basis functions are provided explicitly, which is
-some times necessary, e.g., if part of the form is linearlized manually
-as in::
+sometimes necessary, e.g., if part of the form is linearlized manually
+as in
+
+::
 
   g = Coefficient(element)
   f = inner(grad(w), grad(w))*dx
@@ -1614,7 +1663,9 @@ using automatic differentiation::
 Here ``L`` is defined as a functional with two coefficient functions
 ``x`` and ``y`` from separate finite element spaces.  However, ``F`` and
 ``J`` become linear and bilinear forms respectively with basis functions
-defined on the mixed finite element::
+defined on the mixed finite element
+
+::
 
   M = X + Y
 
@@ -1634,73 +1685,12 @@ The difference is that the forms here have *one* coefficient function
 ``u`` in the mixed space, and the forms above have *two* coefficient
 functions ``x`` and ``y``.
 
-TODO: Move this to implementation part?
-If you wonder how this is all done, a brief explanation follows.
-Recall that a ``Coefficient`` represents a
-sum of unknown coefficients multiplied with unknown
-basis functions in some finite element space.
-
-.. math::
-
-   w(x) = \sum_k w_k \phi_k(x)
-
-Also recall that a ``Argument`` represents any (unknown) basis
-function in some finite element space.
-
-.. math::
-
-   v(x) = \phi_k(x), \qquad \phi_k \in V_h .
-
-A form :math:`L(v; w)` implemented in UFL is intended for discretization
-like
-
-.. math::
-
-   b_i = L(\phi_i; \sum_k w_k \phi_k), \qquad \forall \phi_i \in V_h .
-
-The Jacobi matrix :math:`A_{ij}` of this vector can be obtained by
-differentiation of :math:`b_i` w.r.t. :math:`w_j`, which can be written
-
-.. math::
-
-   A_{ij} = \frac{d b_i}{d w_j} = a(\phi_i, \phi_j; \sum_k w_k \phi_k), \qquad \forall \phi_i \in V_h, \quad \forall \phi_j \in V_h ,
-
-for some form `a`. In UFL, the form `a` can be obtained by
-differentiating `L`.  To manage this, we note that as long as the domain
-:math:\Omega is independent of :math:`w_j`, :math:`\int_\Omega` commutes with :math:`\frac{d}{d
-w_j}`, and we can differentiate the integrand expression instead, e.g.,
-
-.. math::
-
-   L(v; w) = \int_\Omega I_c(v; w) \, dx + \int_{\partial\Omega} I_e(v; w) \, ds, \\
-      \frac{d}{d w_j} L(v; w) = \int_\Omega \frac{d I_c}{d w_j} \, dx + \int_{\partial\Omega} \frac{d I_e}{d w_j} \, ds.
-
-In addition, we need that
-
-.. math::
-
-   \frac{d w}{d w_j} = \phi_j, \qquad \forall \phi_j \in V_h ,
-
-which in UFL can be represented as
-
-.. math::
-
-   w &= \mathtt{Coefficient(element)}, \\
-   v &= \mathtt{Argument(element)}, \\
-   \frac{dw}{d w_j} &= v,
-
-since :math:`w` represents the sum and :math:`v` represents any and all
-basis functions in :math:`V_h`.
-
-Other operators have well defined derivatives, and by repeatedly applying
-the chain rule we can differentiate the integrand automatically.
-
 
 Combining form transformations
 ------------------------------
 
-Form transformations can be combined freely.  Note that to do this,
-derivatives are usually be evaluated before applying e.g. the action of
+Form transformations can be combined freely.  Note that, to do this,
+derivatives are usually evaluated before applying (e.g.) the action of
 a form, because ``derivative`` changes the arity of the form::
 
   element = FiniteElement("CG", cell, 1)
@@ -1729,7 +1719,9 @@ is exported by default, as are forms with the names ``M``, ``L``, and
 and bilinear form respectively.
 
 To export multiple forms and elements or use other names, an explicit
-list with the forms and elements to export can be defined. Simply write::
+list with the forms and elements to export can be defined. Simply write
+
+::
 
   elements = [V, P, TH]
   forms = [a, L, F, J, L2, H1]
diff --git a/doc/sphinx/source/user/internal_representation.rst b/doc/sphinx/source/manual/internal_representation.rst
similarity index 97%
rename from doc/sphinx/source/user/internal_representation.rst
rename to doc/sphinx/source/manual/internal_representation.rst
index 8a6b268..111048a 100644
--- a/doc/sphinx/source/user/internal_representation.rst
+++ b/doc/sphinx/source/manual/internal_representation.rst
@@ -2,16 +2,19 @@
 Internal representation details
 *******************************
 
-FIXME: This chapter is very much outdated.
-Most of the concepts are still the same but
-a lot of the details are different.
+..
+    FIXME: This chapter is very much outdated.
+    Most of the concepts are still the same but
+    a lot of the details are different.
 
 
 This chapter explains how UFL forms and expressions are represented
 in detail. Most operations are mirrored by a representation class,
 e.g., ``Sum`` and ``Product``, which are subclasses
 of ``Expr``.  You can import all of them from the submodule
-``ufl.classes`` by::
+``ufl.classes`` by
+
+::
 
   from ufl.classes import *
 
@@ -140,8 +143,9 @@ Elements
 All finite element classes have a common base class
 ``FiniteElementBase``. The class hierarchy looks like this:
 
+..
 TODO: Class figure.
-
+..
 TODO: Describe all FiniteElementBase subclasses here.
 
 
diff --git a/doc/sphinx/source/user/introduction.rst b/doc/sphinx/source/manual/introduction.rst
similarity index 94%
rename from doc/sphinx/source/user/introduction.rst
rename to doc/sphinx/source/manual/introduction.rst
index 27d01ec..e342143 100644
--- a/doc/sphinx/source/user/introduction.rst
+++ b/doc/sphinx/source/manual/introduction.rst
@@ -6,14 +6,14 @@ The Unified Form Language (UFL) is a domain specific language for
 defining discrete variational forms and functionals in a notation close
 to pen-and-paper formulation.
 
-UFL is part of the FEniCS Project, and is usually used in combination
+UFL is part of the FEniCS Project and is usually used in combination
 with other components from this project to compute solutions to partial
 differential equations. The form compiler FFC uses UFL as its
 end-user interface, producing implementations of the UFC interface as
 output. See DOLFIN for more details about using UFL in an integrated
 problem solving environment.
 
-This manual is intended for different audiences.  If you are an end user
+This manual is intended for different audiences.  If you are an end-user
 and all you want to do is to solve your PDEs with the FEniCS framework,
 you should read :doc:`form_language`, and also :doc:`examples`. These two
 sections explain how to use all operators available in the language and
@@ -23,7 +23,8 @@ The remaining chapters contain more technical details intended for developers
 who need to understand what is happening behind the scenes and modify
 or extend UFL in the future.
 
-:doc:`internal_representation` describes the implementation of the language, in particular
+:doc:`internal_representation` describes the implementation of the language,
+in particular
 how expressions are represented internally by UFL.  This can also be
 useful knowledge to understand error messages and debug errors in your
 form files.
diff --git a/doc/sphinx/source/user/user_manual.rst b/doc/sphinx/source/manual/user_manual.rst
similarity index 100%
rename from doc/sphinx/source/user/user_manual.rst
rename to doc/sphinx/source/manual/user_manual.rst
diff --git a/doc/sphinx/source/releases.rst b/doc/sphinx/source/releases.rst
index 57717e7..796ed29 100644
--- a/doc/sphinx/source/releases.rst
+++ b/doc/sphinx/source/releases.rst
@@ -1,3 +1,7 @@
+.. title:: Release notes
+
+
+=============
 Release notes
 =============
 
@@ -5,4 +9,5 @@ Release notes
    :maxdepth: 2
 
    releases/next
+   releases/v2016.1.0
    releases/v1.6.0
diff --git a/doc/sphinx/source/releases/next.rst b/doc/sphinx/source/releases/next.rst
index 3363ee3..a8dff28 100644
--- a/doc/sphinx/source/releases/next.rst
+++ b/doc/sphinx/source/releases/next.rst
@@ -1,11 +1,38 @@
-Changes in the next release of UFL
-==================================
+===========================
+Changes in the next release
+===========================
+
+
+Summary of changes
+==================
+
+.. note:: Developers should use this page to track and list changes
+          during development. At the time of release, this page should
+          be published (and renamed) to list the most important
+          changes in the new release.
 
 - Deprecate ``.cell()``, ``.domain()``, ``.element()`` in favour of
   ``.ufl_cell()``, ``.ufl_domain()``, ``.ufl_element()``, in multiple
-  classes, to allow closer integration with DOLFIN.
+  classes, to allow closer integration with DOLFIN
 - Remove deprecated properties
-  ``cell.{d,x,n,volume,circumradius,facet_area}``.
+  ``cell.{d,x,n,volume,circumradius,facet_area}``
 - Remove ancient ``form2ufl`` script
 - Large reworking of symbolic geometry pipeline
 - Implement symbolic Piola mappings
+- ``OuterProductCell`` and ``OuterProductElement`` are merged into
+  ``TensorProductCell`` and ``TensorProductElement`` respectively
+- Better degree estimation for quadrilaterals
+- Expansion rules for Q, DQ, RTCE, RTCF, NCE and NCF on tensor product
+  cells
+- Add discontinuous Taylor elements
+- Add support for the mapping ``double covariant Piola`` in ``uflacs``
+- Add support for the mapping ``double contravariant Piola`` in ``uflacs``
+- Support for tensor-valued subelements in ``uflacs`` fixed
+- Replacing ``Discontinuous Lagrange Trace`` with ``HDiv Trace`` and removing ``TraceElement``
+- Assigning ``Discontinuous Lagrange Trace`` and ``DGT`` as aliases for ``HDiv Trace``
+
+Detailed changes
+================
+
+.. note:: At the time of release, make a verbatim copy of the
+          ChangeLog here (and remove this note).
diff --git a/doc/sphinx/source/releases/v1.6.0.rst b/doc/sphinx/source/releases/v1.6.0.rst
index 2f1355f..446bfcf 100644
--- a/doc/sphinx/source/releases/v1.6.0.rst
+++ b/doc/sphinx/source/releases/v1.6.0.rst
@@ -1,7 +1,8 @@
-Changes in UFL 1.6.0
-====================
+========================
+Changes in version 1.6.0
+========================
 
-UFL 1.6.0 was released on 2015-07-28
+UFL 1.6.0 was released on 2015-07-28.
 
 - Change approach to attaching ``__hash__`` implementation to accomodate
   Python 3
diff --git a/doc/sphinx/source/releases/v2016.1.0.rst b/doc/sphinx/source/releases/v2016.1.0.rst
new file mode 100644
index 0000000..cb375e5
--- /dev/null
+++ b/doc/sphinx/source/releases/v2016.1.0.rst
@@ -0,0 +1,27 @@
+===========================
+Changes in version 2016.1.0
+===========================
+
+UFL 2016.1.0 was released on 2016-06-23.
+
+- Add operator A^(i,j) := as_tensor(A, (i,j))
+- Updates to old manual for publishing on fenics-ufl.readthedocs.org
+- Bugfix for ufl files with utf-8 encoding
+- Bugfix in conditional derivatives to avoid inf/nan values in generated
+   code. This bugfix may break ffc if uflacs is not used, to get around
+   that the old workaround in ufl can be enabled by setting
+   ufl.algorithms.apply_derivatives.CONDITIONAL_WORKAROUND = True
+   at the top of your program.
+- Allow sum([expressions]) where expressions are nonscalar by defining
+  expr+0==expr
+- Allow form=0; form -= other;
+- Deprecate .cell(), .domain(), .element() in favour of .ufl_cell(),
+  .ufl_domain(), .ufl_element(), in multiple classes, to allow
+  closer integration with dolfin.
+- Remove deprecated properties cell.{d,x,n,volume,circumradius,facet_area}.
+- Remove ancient form2ufl script
+- Add new class Mesh to replace Domain
+- Add new class FunctionSpace(mesh, element)
+- Make FiniteElement classes take Cell, not Domain.
+- Large reworking of symbolic geometry pipeline
+- Implement symbolic Piola mappings
diff --git a/release.conf b/release.conf
deleted file mode 100644
index b18265b..0000000
--- a/release.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-# Configuration file for fenics-release
-
-PACKAGE="ufl"
-BRANCH="master"
-FILES="ChangeLog ufl/__init__.py setup.py"
-POST_FILES="ChangeLog ufl/__init__.py setup.py"
diff --git a/scripts/ufl-analyse b/scripts/ufl-analyse
index dab709a..ced0259 100755
--- a/scripts/ufl-analyse
+++ b/scripts/ufl-analyse
@@ -6,6 +6,7 @@ __date__ = "2008-05-09"
 # Modified by Anders Logg, 2009.
 # Last changed: 2015-01-05
 
+import io
 import sys, optparse
 from ufl.log import warning
 from ufl.algorithms import load_ufl_file, validate_form, ufl2latex, tree_format
@@ -53,7 +54,9 @@ for filename in filenames:
     # checks while the form is being built
     print("Loading form file '%s'" % filename)
     try:
-        # TODO: Forms that fail will usually fail inside this, which doesn't produce any log... Perhaps we should pass a log file to load_forms?
+        # TODO: Forms that fail will usually fail inside this,
+        # which doesn't produce any log...
+        # Perhaps we should pass a log file to load_forms?
         data = load_ufl_file(filename)
         forms = data.forms
     except:
@@ -62,7 +65,7 @@ for filename in filenames:
 
     outputfilename = filename + ".log"
     if write_file:
-        outputfile = open(outputfilename, "w")
+        outputfile = io.open(outputfilename, "w", encoding="utf-8")
 
     def write(*items):
         text = " ".join(str(s) for s in items)
diff --git a/scripts/ufl-convert b/scripts/ufl-convert
index c6d7345..8da9b9d 100755
--- a/scripts/ufl-convert
+++ b/scripts/ufl-convert
@@ -1,20 +1,35 @@
 #!/usr/bin/env python
-import sys, os, optparse
+from __future__ import print_function
+
+import sys
+import subprocess
+import io
+import os
+import optparse
 from pprint import pprint
 
-from ufl.algorithms import load_ufl_file, ufl2dot, tree_format, forms2latexdocument, preprocess
+from ufl.algorithms import tree_format, compute_form_data
+from ufl.formatting.ufl2dot import ufl2dot
+from ufl.formatting.ufl2latex import forms2latexdocument
+from ufl.algorithms.formfiles import load_ufl_file
 
 # --- Utilities
 
-# Taken from http://ivory.idyll.org/blog/mar-07/replacing-commands-with-subprocess
-from subprocess import Popen, PIPE, STDOUT
+
 def get_status_output(cmd, input=None, cwd=None, env=None):
-    pipe = Popen(cmd, shell=True, cwd=cwd, env=env, stdout=PIPE, stderr=STDOUT)
+    """Replacement for commands.getstatusoutput which does not work on Windows (or Python 3)."""
+    if isinstance(cmd, string_types):
+        cmd = cmd.strip().split()
+    pipe = subprocess.Popen(cmd, shell=False, cwd=cwd, env=env,
+                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     (output, errout) = pipe.communicate(input=input)
     assert not errout
     status = pipe.returncode
+    if isinstance(output, bytes):
+        output = output.decode('utf-8')
     return (status, output)
 
+
 def runcmd(cmd):
     status, output = get_status_output(cmd)
     if status != 0:
@@ -24,9 +39,8 @@ def runcmd(cmd):
 
 def write_file(filename, text):
     "Write text to a file and close it."
-    f = open(filename, "w")
-    f.write(text)
-    f.close()
+    with io.open(filename, "w", encoding="utf-8") as f:
+        f.write(text)
     print("Wrote file %s" % filename)
 
 # --- Option parsing
@@ -45,13 +59,11 @@ option_list = [ \
     opt("outputdir", "o", "str", "", "Output directory."),
     opt("inputdir",  "i", "str", "", "Input directory."),
     # Expression transformations:
-    opt("compile",   "c", "int", 0, "'Compile' forms: apply expression transformations like in a quadrature based form compilation."),
     opt("labeling",  "l", "str", "repr", "Set to 'repr' or 'compact' for different naming of graph nodes."),
+    opt("compile",   "c", "int", 0, "'Compile' forms: apply expression transformations like in a quadrature based form compilation. Only used for latex formatting."),
     # Output formats:
     opt("format",    "f", "str", "", "Rendering format (str, repr, tree, dot, latex)."),
     opt("filetype",  "t", "str", "", "Output file type (txt, py, dot, tex, ps, pdf, png)."),
-    # Additional actions:
-    opt("show",      "s", "int", 0, "Open in an external viewer."),
     ]
 
 parser = optparse.OptionParser(usage=usage, option_list=option_list)
@@ -76,28 +88,14 @@ for arg in args:
     if ext != ".ufl":
         print("Expecting a .ufl file, not ", uflfilename)
         sys.exit(-1)
-    #print "uflfilename =", uflfilename
-    #print "path =", path
-    #print "name =", name
-    #print "basename =", basename
-    #print "ext =", ext
 
     # 1) Load forms
-    #forms = load_forms(uflfilename)
-    #formdatas = [f.compute_form_data() for f in forms]
     ufl_data = load_ufl_file(uflfilename)
     forms = ufl_data.forms
     #expressions = ufl_data.expressions # TODO: Allow rendering expressions without form stuff!
 
     # Preprocess forms
-    for f in forms:
-        f.compute_form_data(object_names=ufl_data.object_names)
-
-    # 2) Transform forms
-    compiled_forms = []
-    if options.compile:
-        pass # TODO
-        #compiled_forms = [compile_form(form) for form in forms]
+    form_datas = [compute_form_data(f) for f in forms]
 
     # 3) Render result
     format = options.format
@@ -105,34 +103,38 @@ for arg in args:
     # Make format string conform
     if format == "latex":
         format = "tex"
-    if format == "str":
-        if options.compile:
-            print("Warning: compile option not used.")
-        rendered = "\n\n".join("Form %s:\n%s\n" % (f.form_data().name, str(f)) for f in forms)
-        #rendered = "\n\n".join("Form %s:\n%s\n" % (f.form_data().name, str(f.form_data())) for f in forms)
-    elif format == "repr":
-        if options.compile:
-            print("Warning: compile option not used.")
-        rendered = "\n\n".join("Form %s:\n%s\n" % (f.form_data().name, repr(f)) for f in forms)
-    elif format == "tree":
-        if options.compile:
-            print("Warning: compile option not used.")
-        rendered = "\n\n".join("Form %s:\n%s\n" % (f.form_data().name, tree_format(f)) for f in forms)
+    if format == "tex":
+        rendered = forms2latexdocument(forms, uflfilename, compile=options.compile)
+    elif format in ("str", "repr", "tree"):
+        data = []
+        for i, fd in enumerate(form_datas):
+            f = fd.original_form
+            name = ufl_data.object_names.get(f, "form")
+
+            if format == "str":
+                s = str(f)
+            elif format == "repr":
+                s = repr(f)
+            elif format == "tree":
+                s = tree_format(f)
+            tmp = "Form %s:\n%s\n" % (name, s)
+
+            data.append(tmp)
+        rendered = "\n\n".join(data)
     elif format == "dot":
-        if options.compile:
-            print("Warning: compile option not used.")
         data = []
         nodeoffset = 0
-        for i, f in enumerate(forms):
+        for i, fd in enumerate(form_datas):
+            f = fd.original_form
+            name = ufl_data.object_names.get(f, "form")
+
             begin = (i == 0)
             end = (i == len(forms) - 1)
-            dot, nodeoffset = ufl2dot(f, f.form_data().name, nodeoffset, begin, end,
+            dot, nodeoffset = ufl2dot(f, name, nodeoffset, begin, end,
                                       options.labeling, ufl_data.object_names)
-            tmp = "/* Form %s: */\n%s\n" % (f.form_data().name, dot)
+            tmp = "/* Form %s: */\n%s\n" % (name, dot)
             data.append(tmp)
         rendered = "\n\n".join(data)
-    elif format == "tex":
-        rendered = forms2latexdocument(forms, uflfilename, compile=options.compile)
     else:
         print("Unknown rendering format ", format)
         sys.exit(-1)
@@ -171,9 +173,6 @@ for arg in args:
             flags = "-file-line-error-style -interaction=nonstopmode"
             cmd = "pdflatex %s '%s'" % (flags, texfile)
             runcmd(cmd)
-            if options.show:
-                print(outputfilename)
-                runcmd("evince '%s' &" % outputfilename)
         else:
             print("Unknown format and filetype combination:", format, filetype)
             sys.exit(-1)
@@ -184,16 +183,11 @@ for arg in args:
         write_file(tempfile, rendered)
         if filetype in ("png", "ps", "svg", "gif", "dia", "imap", "cmapx"): # taken from "man dot"
             runcmd("dot -T%s -o'%s' '%s'" % (filetype, outputfilename, tempfile))
-            if options.show:
-                runcmd("evince '%s' &" % outputfilename)
         elif filetype == "pdf":
             psfilename = os.path.join(options.outputdir, basename + ".ps")
             pdffilename = os.path.join(options.outputdir, basename + ".pdf")
             runcmd("dot -T%s -o'%s' '%s'" % (filetype, psfilename, tempfile))
             runcmd("ps2pdf '%s' '%s'" % (psfilename, pdffilename))
-            if options.show:
-                print(pdffilename)
-                runcmd("evince '%s' &" % pdffilename)
         else:
             print("Unknown format and filetype combination:", format, filetype)
             sys.exit(-1)
diff --git a/scripts/ufl-version b/scripts/ufl-version
index b661372..c2fd213 100755
--- a/scripts/ufl-version
+++ b/scripts/ufl-version
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
-
-# Copyright (C) 2011 Anders Logg.
+# -*- coding: utf-8 -*-
+# Copyright (C) 2011-2016 Anders Logg.
 #
 # This file is part of UFL.
 #
@@ -16,11 +16,9 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
-#
-# First added:  2011-06-14
-# Last changed: 2011-06-14
 
-# This is a simple script that just prints the UFL version number.
+"""This is a simple script that just prints the UFL version number."""
 
+from __future__ import print_function
 from ufl import __version__
 print(__version__)
diff --git a/scripts/ufl2py b/scripts/ufl2py
index 7a222ab..cd9b9b3 100755
--- a/scripts/ufl2py
+++ b/scripts/ufl2py
@@ -3,7 +3,8 @@
 from __future__ import with_statement
 
 import os, sys, optparse
-from ufl.algorithms import FormData, read_ufl_file, load_forms, validate_form, ufl2latex, tree_format
+from ufl.algorithms import validate_form, ufl2latex, tree_format
+from ufl.algorithms.formfiles import read_ufl_file
 
 # Get commandline options
 
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..dc791ed
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,3 @@
+[flake8]
+ignore = E501,E226,W503,E127,E123,E128,E265
+exclude = .git,__pycache__,doc/sphinx/source/conf.py,build,dist,test
diff --git a/setup.py b/setup.py
index 49e4ac2..684278c 100755
--- a/setup.py
+++ b/setup.py
@@ -1,26 +1,34 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 from __future__ import print_function
 
-try:
-    from setuptools import setup
-except ImportError:
-    from distutils.core import setup
-
-from os.path import join as pjoin, split as psplit
+from setuptools import setup
+from os.path import join, split
 import re
 import sys
 import platform
 import codecs
 
+module_name = "ufl"
+
 if sys.version_info < (2, 7):
     print("Python 2.7 or higher required, please upgrade.")
     sys.exit(1)
 
-scripts = [pjoin("scripts", "ufl-analyse"),
-           pjoin("scripts", "ufl-convert"),
-           pjoin("scripts", "ufl-version"),
-           pjoin("scripts", "ufl2py")]
+# __init__.py has UTF-8 characters. Works in Python 2 and 3.
+version = re.findall('__version__ = "(.*)"',
+                     codecs.open(join(module_name, '__init__.py'), 'r',
+                                 encoding='utf-8').read())[0]
+
+url = "https://bitbucket.org/fenics-project/%s/" % module_name
+tarball = None
+if 'dev' not in version:
+    tarball = url + "downloads/%s-%s.tar.gz" % (module_name, version)
+
+script_names = ("ufl-analyse", "ufl-convert", "ufl-version", "ufl2py")
+
+scripts = [join("scripts", script) for script in script_names]
+man_files = [join("doc", "man", "man1", "%s.1.gz" % (script,)) for script in script_names]
+data_files = [(join("share", "man", "man1"), man_files)]
 
 if platform.system() == "Windows" or "bdist_wininst" in sys.argv:
     # In the Windows command prompt we can't execute Python scripts
@@ -29,40 +37,41 @@ if platform.system() == "Windows" or "bdist_wininst" in sys.argv:
     batch_files = []
     for script in scripts:
         batch_file = script + ".bat"
-        f = open(batch_file, "w")
-        f.write('python "%%~dp0\%s" %%*' % psplit(script)[1])
-        f.close()
+        with open(batch_file, "w") as f:
+            f.write(sys.executable + ' "%%~dp0\%s" %%*' % split(script)[1])
         batch_files.append(batch_file)
     scripts.extend(batch_files)
 
-# __init__.py has UTF-8 characters. Works in Python 2 and 3.
-version = re.findall('__version__ = "(.*)"',
-                     codecs.open('ufl/__init__.py', 'r', encoding='utf-8').read())[0]
-
-url = "https://bitbucket.org/fenics-project/ufl/"
-tarball = None
-if not 'dev' in version:
-    tarball = url + "downloads/ufl-%s.tar.gz" % version
+CLASSIFIERS = """\
+Development Status :: 5 - Production/Stable
+Intended Audience :: Developers
+Intended Audience :: Science/Research
+License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
+Operating System :: POSIX
+Operating System :: POSIX :: Linux
+Operating System :: MacOS :: MacOS X
+Operating System :: Microsoft :: Windows
+Programming Language :: Python
+Programming Language :: Python :: 2
+Programming Language :: Python :: 2.7
+Programming Language :: Python :: 3
+Programming Language :: Python :: 3.4
+Programming Language :: Python :: 3.5
+Programming Language :: Python :: 3.6
+Topic :: Scientific/Engineering :: Mathematics
+Topic :: Software Development :: Libraries :: Python Modules
+"""
 
 setup(name="UFL",
-      version = version,
-      description = "Unified Form Language",
-      author = "Martin Sandve Alnæs, Anders Logg",
-      author_email = "fenics-dev at googlegroups.com",
-      url = url,
-      download_url = tarball,
-      classifiers=[
-          'Development Status :: 5 - Production/Stable',
-          'Intended Audience :: Developers',
-          'Intended Audience :: Science/Research',
-          'Programming Language :: Python :: 2.7',
-          'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
-          'Topic :: Scientific/Engineering :: Mathematics',
-          'Topic :: Software Development :: Compilers',
-          'Topic :: Software Development :: Libraries :: Python Modules',
-          ],
-      scripts = scripts,
-      packages = [
+      version=version,
+      description="Unified Form Language",
+      author="Martin Sandve Alnæs, Anders Logg",
+      author_email="fenics-dev at googlegroups.com",
+      url=url,
+      download_url=tarball,
+      classifiers=[_f for _f in CLASSIFIERS.split('\n') if _f],
+      scripts=scripts,
+      packages=[
           "ufl",
           "ufl.utils",
           "ufl.finiteelement",
@@ -70,12 +79,8 @@ setup(name="UFL",
           "ufl.corealg",
           "ufl.algorithms",
           "ufl.formatting",
-          ],
-      package_dir = {"ufl": "ufl"},
-      install_requires = ["numpy", "six"],
-      data_files = [(pjoin("share", "man", "man1"),
-                     [pjoin("doc", "man", "man1", "ufl-analyse.1.gz"),
-                      pjoin("doc", "man", "man1", "ufl-convert.1.gz"),
-                      pjoin("doc", "man", "man1", "ufl-version.1.gz"),
-                      pjoin("doc", "man", "man1", "ufl2py.1.gz"),
-                     ])])
+      ],
+      package_dir={"ufl": "ufl"},
+      install_requires=["numpy", "six"],
+      data_files=data_files
+      )
diff --git a/test/conftest.py b/test/conftest.py
index 2f45f33..aeb0dd3 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -6,6 +6,7 @@ import ufl
 from ufl import as_ufl, inner, dx
 from ufl.algorithms import compute_form_data
 
+
 class Tester:
 
     def assertTrue(self, a):
@@ -50,11 +51,14 @@ class Tester:
         self.assertEqual(A.ufl_shape, B.ufl_shape)
         self.assertEqual(inner(A-B, A-B)(None), 0)
 
+
 @pytest.fixture(scope="session")
 def self():
     return Tester()
 
 _all_cells = [ufl.interval, ufl.triangle, ufl.tetrahedron]
+
+
 @pytest.fixture(params=_all_cells)
 def cell(request):
     return request.param
diff --git a/test/sourceme.sh b/test/sourceme.sh
deleted file mode 100644
index f5037ba..0000000
--- a/test/sourceme.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-# Set python path to find the local uninstalled ufl version
-export PYTHONPATH="`pwd`/..:$PYTHONPATH"
-export PATH="`pwd`/../scripts:$PATH"
-echo PYTHONPATH is now $PYTHONPATH
-echo PATH is now $PATH
diff --git a/test/test_algorithms.py b/test/test_algorithms.py
index 3790622..315be4d 100755
--- a/test/test_algorithms.py
+++ b/test/test_algorithms.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env py.test
 # -*- coding: utf-8 -*-
 
 __authors__ = "Martin Sandve Alnæs"
diff --git a/test/test_analyse_demos.py b/test/test_analyse_demos.py
index 8873558..4143285 100755
--- a/test/test_analyse_demos.py
+++ b/test/test_analyse_demos.py
@@ -1,76 +1,31 @@
-#!/usr/bin/env py.test
 # -*- coding: utf-8 -*-
 
+from __future__ import print_function
+
 __authors__ = "Martin Sandve Alnæs"
 __date__ = "2008-09-28 -- 2008-09-28"
 
 import os
 import pytest
-from ufl.algorithms import load_ufl_file, validate_form
+from ufl.algorithms import load_ufl_file, compute_form_data, validate_form
 from glob import glob
 
-# Taken from
-# http://ivory.idyll.org/blog/mar-07/replacing-commands-with-subprocess
-from subprocess import Popen, PIPE, STDOUT
-
-
-def get_status_output(cmd, input=None, cwd=None, env=None):
-    pipe = Popen(cmd, shell=True, cwd=cwd, env=env, stdout=PIPE, stderr=STDOUT)
-    (output, errout) = pipe.communicate(input=input)
-    assert not errout
-    status = pipe.returncode
-    return (status, output)
 
-
-def _test_all_demos():
-    # Check all at once
-    skip = set(glob("../demo/_*.ufl"))
-    filenames = [f for f in sorted(glob("../demo/*.ufl")) if not f in skip]
-    cmd = "ufl-analyse %s" % " ".join(filenames)
-    status, output = get_status_output(cmd)
-    assert status == 0
+demodir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "demo"))
 
 
 def get_demo_filenames():
-    skiplist = glob("../demo/_*.ufl")  # + ["../demo/Hyperelasticity3D.ufl"]
-    filenames = []
-    for f in sorted(glob("../demo/*.ufl")):
-        if f in skiplist:
-            print(("Skipping demo %s" % f))
-        else:
-            filenames.append(f)
+    filenames = sorted(
+        set(glob(os.path.join(demodir, "*.ufl")))
+        - set(glob(os.path.join(demodir, "_*.ufl")))
+        )
     return filenames
 
 
-def xtest_each_demo_with_ufl_analyse():
-    "Check each file from cmdline with ufl-analyse."
-    for f in get_demo_filenames():
-        cmd = "ufl-analyse %s" % f
-        status, output = get_status_output(cmd)
-        assert status == 0
-        if status == 0:
-            print(("Successfully analysed %s without problems" % f))
-        else:
-            name = "%s.analysis" % f
-            print(("Encountered problems when analysing %s "
-                  "(return code %s), see output in file %s" % (f, status, name)))
-            of = open(name, "w")
-            of.write(output)
-            of.close()
-            print()
-            print(output)
-            print()
-
-
-def test_each_demo_with_validate_form():
+ at pytest.mark.parametrize("filename", get_demo_filenames())
+def test_demo_files(filename):
     "Check each form in each file with validate_form."
-    for filename in get_demo_filenames():
-        print(filename)
-        data = load_ufl_file(filename)
-        for form in data.forms:
-            try:
-                validate_form(form)
-                excepted = 0
-            except:
-                excepted = 1
-            assert excepted == 0, filename
+    data = load_ufl_file(filename)
+    for form in data.forms:
+        #fd = compute_form_data(form)  # TODO: Skip failure examples
+        validate_form(form)
diff --git a/test/test_apply_algebra_lowering.py b/test/test_apply_algebra_lowering.py
index c86ed5e..a9a097b 100755
--- a/test/test_apply_algebra_lowering.py
+++ b/test/test_apply_algebra_lowering.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env pytest
 # -*- coding: utf-8 -*-
 
 import pytest
@@ -6,86 +5,106 @@ from ufl import *
 from ufl.compound_expressions import *
 from ufl.algorithms.renumbering import renumber_indices
 
+
 @pytest.fixture
 def A0(request):
     return Coefficient(FiniteElement("CG", interval, 1))
 
+
 @pytest.fixture
 def A1(request):
     return Coefficient(TensorElement("CG", interval, 1))
 
+
 @pytest.fixture
 def A2(request):
     return Coefficient(TensorElement("CG", triangle, 1))
 
+
 @pytest.fixture
 def A3(request):
     return Coefficient(TensorElement("CG", tetrahedron, 1))
 
+
 @pytest.fixture
 def A21(request):
-    return Coefficient(TensorElement("CG", triangle, 1, shape=(2,1)))
+    return Coefficient(TensorElement("CG", triangle, 1, shape=(2, 1)))
+
 
 @pytest.fixture
 def A31(request):
-    return Coefficient(TensorElement("CG", triangle, 1, shape=(3,1)))
+    return Coefficient(TensorElement("CG", triangle, 1, shape=(3, 1)))
+
 
 @pytest.fixture
 def A32(request):
-    return Coefficient(TensorElement("CG", triangle, 1, shape=(3,2)))
+    return Coefficient(TensorElement("CG", triangle, 1, shape=(3, 2)))
+
 
 def test_determinant0(A0):
     assert determinant_expr(A0) == A0
 
+
 def test_determinant1(A1):
-    assert determinant_expr(A1) == A1[0,0]
+    assert determinant_expr(A1) == A1[0, 0]
+
 
 def test_determinant2(A2):
-    assert determinant_expr(A2) == A2[0,0]*A2[1,1] - A2[0,1]*A2[1,0]
+    assert determinant_expr(A2) == A2[0, 0]*A2[1, 1] - A2[0, 1]*A2[1, 0]
+
 
 def test_determinant3(A3):
-    assert determinant_expr(A3) == (A3[0,0]*(A3[1,1]*A3[2,2] - A3[1,2]*A3[2,1])
-                                   +A3[0,1]*(A3[1,2]*A3[2,0] - A3[1,0]*A3[2,2])
-                                   +A3[0,2]*(A3[1,0]*A3[2,1] - A3[1,1]*A3[2,0]))
+    assert determinant_expr(A3) == (A3[0, 0]*(A3[1, 1]*A3[2, 2] - A3[1, 2]*A3[2, 1])
+                                    + A3[0, 1]*(A3[1, 2]*A3[2, 0] - A3[1, 0]*A3[2, 2])
+                                    + A3[0, 2]*(A3[1, 0]*A3[2, 1] - A3[1, 1]*A3[2, 0]))
+
 
 def test_pseudo_determinant21(A21):
     i = Index()
-    assert renumber_indices(determinant_expr(A21)) == renumber_indices(sqrt(A21[i,0]*A21[i,0]))
+    assert renumber_indices(determinant_expr(A21)) == renumber_indices(sqrt(A21[i, 0]*A21[i, 0]))
+
 
 def test_pseudo_determinant31(A31):
     i = Index()
-    assert renumber_indices(determinant_expr(A31)) == renumber_indices(sqrt((A31[i,0]*A31[i,0])))
+    assert renumber_indices(determinant_expr(A31)) == renumber_indices(sqrt((A31[i, 0]*A31[i, 0])))
+
 
 def test_pseudo_determinant32(A32):
     i = Index()
-    c = cross_expr(A32[:,0], A32[:,1])
+    c = cross_expr(A32[:, 0], A32[:, 1])
     assert renumber_indices(determinant_expr(A32)) == renumber_indices(sqrt(c[i]*c[i]))
 
 
 def test_inverse0(A0):
-    expected = 1.0/A0 # stays scalar
+    expected = 1.0/A0  # stays scalar
     assert inverse_expr(A0) == renumber_indices(expected)
 
+
 def test_inverse1(A1):
-    expected = as_tensor(((1.0/A1[0,0],),)) # reshaped into 1x1 tensor
+    expected = as_tensor(((1.0/A1[0, 0],),))  # reshaped into 1x1 tensor
     assert inverse_expr(A1) == renumber_indices(expected)
 
+
 def xtest_inverse2(A2):
     expected = todo
     assert inverse_expr(A2) == renumber_indices(expected)
 
+
 def xtest_inverse3(A3):
     expected = todo
     assert inverse_expr(A3) == renumber_indices(expected)
 
+
 def xtest_pseudo_inverse21(A21):
     expected = todo
     assert renumber_indices(inverse_expr(A21)) == renumber_indices(expected)
 
+
 def xtest_pseudo_inverse31(A31):
     expected = todo
     assert renumber_indices(inverse_expr(A31)) == renumber_indices(expected)
 
+
 def xtest_pseudo_inverse32(A32):
     expected = todo
     assert renumber_indices(inverse_expr(A32)) == renumber_indices(expected)
diff --git a/test/test_apply_function_pullbacks.py b/test/test_apply_function_pullbacks.py
index d00ed13..991714b 100755
--- a/test/test_apply_function_pullbacks.py
+++ b/test/test_apply_function_pullbacks.py
@@ -9,6 +9,7 @@ from ufl.algorithms.apply_function_pullbacks import apply_function_pullbacks, ap
 from ufl.algorithms.renumbering import renumber_indices
 from ufl.classes import Jacobian, JacobianInverse, JacobianDeterminant, ReferenceValue, CellOrientation
 
+
 def check_single_function_pullback(g, mappings):
     expected = mappings[g]
     actual = apply_single_function_pullbacks(g)
@@ -29,6 +30,7 @@ def check_single_function_pullback(g, mappings):
         print()
     assert ract == rexp
 
+
 def test_apply_single_function_pullbacks_triangle3d():
     triangle3d = Cell("triangle", geometric_dimension=3)
     cell = triangle3d
@@ -49,7 +51,7 @@ def test_apply_single_function_pullbacks_triangle3d():
     Tm = Vc*T
     Sm = T*S
 
-    Vd0 = Vd*U0 # case from failing ffc demo
+    Vd0 = Vd*U0  # case from failing ffc demo
 
     W = S*T*Vc*Vd*V*U
 
@@ -67,7 +69,7 @@ def test_apply_single_function_pullbacks_triangle3d():
     tm = Coefficient(Tm)
     sm = Coefficient(Sm)
 
-    vd0m = Coefficient(Vd0) # case from failing ffc demo
+    vd0m = Coefficient(Vd0)  # case from failing ffc demo
 
     w = Coefficient(W)
 
@@ -100,19 +102,19 @@ def test_apply_single_function_pullbacks_triangle3d():
     J = Jacobian(domain)
     detJ = JacobianDeterminant(domain)
     Jinv = JacobianInverse(domain)
-    #o = CellOrientation(domain)
+    # o = CellOrientation(domain)
     i, j, k, l = indices(4)
 
     # Contravariant H(div) Piola mapping:
-    M_hdiv = ((1.0/detJ) * J) # Not applying cell orientation here
+    M_hdiv = ((1.0/detJ) * J)  # Not applying cell orientation here
     # Covariant H(curl) Piola mapping: Jinv.T
 
     mappings = {
         # Simple elements should get a simple representation
         u: ru,
         v: rv,
-        vd: as_vector(M_hdiv[i,j]*rvd[j], i),
-        vc: as_vector(Jinv[j,i]*rvc[j], i),
+        vd: as_vector(M_hdiv[i, j]*rvd[j], i),
+        vc: as_vector(Jinv[j, i]*rvc[j], i),
         t: rt,
         s: as_tensor([[rs[0], rs[1], rs[2]],
                       [rs[1], rs[3], rs[4]],
@@ -126,47 +128,47 @@ def test_apply_single_function_pullbacks_triangle3d():
             rvdm[1],
             rvdm[2],
             # Vd
-            M_hdiv[0,j]*as_vector([rvdm[3], rvdm[4]])[j],
-            M_hdiv[1,j]*as_vector([rvdm[3], rvdm[4]])[j],
-            M_hdiv[2,j]*as_vector([rvdm[3], rvdm[4]])[j],
-            ]),
+            M_hdiv[0, j]*as_vector([rvdm[3], rvdm[4]])[j],
+            M_hdiv[1, j]*as_vector([rvdm[3], rvdm[4]])[j],
+            M_hdiv[2, j]*as_vector([rvdm[3], rvdm[4]])[j],
+    ]),
         vcm: as_vector([
             # Vd
-            M_hdiv[0,j]*as_vector([rvcm[0], rvcm[1]])[j],
-            M_hdiv[1,j]*as_vector([rvcm[0], rvcm[1]])[j],
-            M_hdiv[2,j]*as_vector([rvcm[0], rvcm[1]])[j],
+            M_hdiv[0, j]*as_vector([rvcm[0], rvcm[1]])[j],
+            M_hdiv[1, j]*as_vector([rvcm[0], rvcm[1]])[j],
+            M_hdiv[2, j]*as_vector([rvcm[0], rvcm[1]])[j],
             # Vc
-            Jinv[i,0]*as_vector([rvcm[2], rvcm[3]])[i],
-            Jinv[i,1]*as_vector([rvcm[2], rvcm[3]])[i],
-            Jinv[i,2]*as_vector([rvcm[2], rvcm[3]])[i],
-            ]),
+            Jinv[i, 0]*as_vector([rvcm[2], rvcm[3]])[i],
+            Jinv[i, 1]*as_vector([rvcm[2], rvcm[3]])[i],
+            Jinv[i, 2]*as_vector([rvcm[2], rvcm[3]])[i],
+    ]),
         tm: as_vector([
             # Vc
-            Jinv[i,0]*as_vector([rtm[0], rtm[1]])[i],
-            Jinv[i,1]*as_vector([rtm[0], rtm[1]])[i],
-            Jinv[i,2]*as_vector([rtm[0], rtm[1]])[i],
+            Jinv[i, 0]*as_vector([rtm[0], rtm[1]])[i],
+            Jinv[i, 1]*as_vector([rtm[0], rtm[1]])[i],
+            Jinv[i, 2]*as_vector([rtm[0], rtm[1]])[i],
             # T
             rtm[2], rtm[3], rtm[4],
             rtm[5], rtm[6], rtm[7],
             rtm[8], rtm[9], rtm[10],
-            ]),
+    ]),
         sm: as_vector([
             # T
             rsm[0], rsm[1], rsm[2],
             rsm[3], rsm[4], rsm[5],
             rsm[6], rsm[7], rsm[8],
             # S
-            rsm[ 9], rsm[10], rsm[11],
+            rsm[9], rsm[10], rsm[11],
             rsm[10], rsm[12], rsm[13],
             rsm[11], rsm[13], rsm[14],
-            ]),
+    ]),
         # Case from failing ffc demo:
         vd0m: as_vector([
-            M_hdiv[0,j]*as_vector([rvd0m[0],rvd0m[1]])[j],
-            M_hdiv[1,j]*as_vector([rvd0m[0],rvd0m[1]])[j],
-            M_hdiv[2,j]*as_vector([rvd0m[0],rvd0m[1]])[j],
+            M_hdiv[0, j]*as_vector([rvd0m[0], rvd0m[1]])[j],
+            M_hdiv[1, j]*as_vector([rvd0m[0], rvd0m[1]])[j],
+            M_hdiv[2, j]*as_vector([rvd0m[0], rvd0m[1]])[j],
             rvd0m[2]
-            ]),
+    ]),
         # This combines it all:
         w: as_vector([
             # S
@@ -178,21 +180,21 @@ def test_apply_single_function_pullbacks_triangle3d():
             rw[9], rw[10], rw[11],
             rw[12], rw[13], rw[14],
             # Vc
-            Jinv[i,0]*as_vector([rw[15], rw[16]])[i],
-            Jinv[i,1]*as_vector([rw[15], rw[16]])[i],
-            Jinv[i,2]*as_vector([rw[15], rw[16]])[i],
+            Jinv[i, 0]*as_vector([rw[15], rw[16]])[i],
+            Jinv[i, 1]*as_vector([rw[15], rw[16]])[i],
+            Jinv[i, 2]*as_vector([rw[15], rw[16]])[i],
             # Vd
-            M_hdiv[0,j]*as_vector([rw[17], rw[18]])[j],
-            M_hdiv[1,j]*as_vector([rw[17], rw[18]])[j],
-            M_hdiv[2,j]*as_vector([rw[17], rw[18]])[j],
+            M_hdiv[0, j]*as_vector([rw[17], rw[18]])[j],
+            M_hdiv[1, j]*as_vector([rw[17], rw[18]])[j],
+            M_hdiv[2, j]*as_vector([rw[17], rw[18]])[j],
             # V
             rw[19],
             rw[20],
             rw[21],
             # U
             rw[22],
-            ]),
-        }
+    ]),
+    }
 
     # Check functions of various elements outside a mixed context
     check_single_function_pullback(u, mappings)
@@ -285,8 +287,8 @@ def test_apply_single_function_pullbacks_triangle():
         # Simple elements should get a simple representation
         u: ru,
         v: rv,
-        vd: as_vector(M_hdiv[i,j]*rvd[j], i),
-        vc: as_vector(Jinv[j,i]*rvc[j], i),
+        vd: as_vector(M_hdiv[i, j]*rvd[j], i),
+        vc: as_vector(Jinv[j, i]*rvc[j], i),
         t: rt,
         s: as_tensor([[rs[0], rs[1]], [rs[1], rs[2]]]),
         # Mixed elements become a bit more complicated
@@ -297,25 +299,25 @@ def test_apply_single_function_pullbacks_triangle():
             rvdm[0],
             rvdm[1],
             # Vd
-            M_hdiv[0,j]*as_vector([rvdm[2], rvdm[3]])[j],
-            M_hdiv[1,j]*as_vector([rvdm[2], rvdm[3]])[j],
-            ]),
+            M_hdiv[0, j]*as_vector([rvdm[2], rvdm[3]])[j],
+            M_hdiv[1, j]*as_vector([rvdm[2], rvdm[3]])[j],
+    ]),
         vcm: as_vector([
             # Vd
-            M_hdiv[0,j]*as_vector([rvcm[0], rvcm[1]])[j],
-            M_hdiv[1,j]*as_vector([rvcm[0], rvcm[1]])[j],
+            M_hdiv[0, j]*as_vector([rvcm[0], rvcm[1]])[j],
+            M_hdiv[1, j]*as_vector([rvcm[0], rvcm[1]])[j],
             # Vc
-            Jinv[i,0]*as_vector([rvcm[2], rvcm[3]])[i],
-            Jinv[i,1]*as_vector([rvcm[2], rvcm[3]])[i],
-            ]),
+            Jinv[i, 0]*as_vector([rvcm[2], rvcm[3]])[i],
+            Jinv[i, 1]*as_vector([rvcm[2], rvcm[3]])[i],
+    ]),
         tm: as_vector([
             # Vc
-            Jinv[i,0]*as_vector([rtm[0], rtm[1]])[i],
-            Jinv[i,1]*as_vector([rtm[0], rtm[1]])[i],
+            Jinv[i, 0]*as_vector([rtm[0], rtm[1]])[i],
+            Jinv[i, 1]*as_vector([rtm[0], rtm[1]])[i],
             # T
             rtm[2], rtm[3],
             rtm[4], rtm[5],
-            ]),
+    ]),
         sm: as_vector([
             # T
             rsm[0], rsm[1],
@@ -323,7 +325,7 @@ def test_apply_single_function_pullbacks_triangle():
             # S
             rsm[4], rsm[5],
             rsm[5], rsm[6],
-            ]),
+    ]),
         # This combines it all:
         w: as_vector([
             # S
@@ -333,18 +335,18 @@ def test_apply_single_function_pullbacks_triangle():
             rw[3], rw[4],
             rw[5], rw[6],
             # Vc
-            Jinv[i,0]*as_vector([rw[7], rw[8]])[i],
-            Jinv[i,1]*as_vector([rw[7], rw[8]])[i],
+            Jinv[i, 0]*as_vector([rw[7], rw[8]])[i],
+            Jinv[i, 1]*as_vector([rw[7], rw[8]])[i],
             # Vd
-            M_hdiv[0,j]*as_vector([rw[9], rw[10]])[j],
-            M_hdiv[1,j]*as_vector([rw[9], rw[10]])[j],
+            M_hdiv[0, j]*as_vector([rw[9], rw[10]])[j],
+            M_hdiv[1, j]*as_vector([rw[9], rw[10]])[j],
             # V
             rw[11],
             rw[12],
             # U
             rw[13],
-            ]),
-        }
+    ]),
+    }
 
     # Check functions of various elements outside a mixed context
     check_single_function_pullback(u, mappings)
diff --git a/test/test_apply_restrictions.py b/test/test_apply_restrictions.py
index aafa24c..c9775e1 100755
--- a/test/test_apply_restrictions.py
+++ b/test/test_apply_restrictions.py
@@ -3,9 +3,10 @@
 
 from pytest import raises
 from ufl import *
-from ufl.algorithms.apply_restrictions import apply_restrictions
+from ufl.algorithms.apply_restrictions import apply_restrictions, apply_default_restrictions
 from ufl.algorithms.renumbering import renumber_indices
 
+
 def test_apply_restrictions():
     cell = triangle
     V0 = FiniteElement("DG", cell, 0)
@@ -36,10 +37,10 @@ def test_apply_restrictions():
     assert apply_restrictions((grad(f) + grad(g))('-')) == (grad(f)('-') + grad(g)('-'))
 
     # x is the same from both sides but computed from one of them
-    assert apply_restrictions(x) == x('+')
+    assert apply_default_restrictions(x) == x('+')
 
     # n on a linear mesh is opposite pointing from the other side
     assert apply_restrictions(n('+')) == n('+')
     assert renumber_indices(apply_restrictions(n('-'))) == renumber_indices(as_tensor(-1*n('+')[i], i))
     # This would be nicer, but -f is translated to -1*f which is translated to as_tensor(-1*f[i], i).
-    #assert apply_restrictions(n('-')) == -n('+')
+    # assert apply_restrictions(n('-')) == -n('+')
diff --git a/test/test_arithmetic.py b/test/test_arithmetic.py
index dea5aa9..bb214c9 100755
--- a/test/test_arithmetic.py
+++ b/test/test_arithmetic.py
@@ -6,6 +6,7 @@ import pytest
 from ufl import *
 from ufl.classes import Division, FloatValue, IntValue
 
+
 def test_scalar_casting(self):
     f = as_ufl(2.0)
     r = as_ufl(4)
@@ -14,31 +15,37 @@ def test_scalar_casting(self):
     assert float(f) == 2.0
     assert int(r) == 4
 
+
 def test_ufl_float_division(self):
-    d = SpatialCoordinate(triangle)[0] / 10.0 # TODO: Use mock instead of x
+    d = SpatialCoordinate(triangle)[0] / 10.0  # TODO: Use mock instead of x
     self.assertIsInstance(d, Division)
 
+
 def test_float_ufl_division(self):
-    d = 3.14 / SpatialCoordinate(triangle)[0] # TODO: Use mock instead of x
+    d = 3.14 / SpatialCoordinate(triangle)[0]  # TODO: Use mock instead of x
     self.assertIsInstance(d, Division)
 
+
 def test_float_division(self):
     d = as_ufl(20.0) / 10.0
     self.assertIsInstance(d, FloatValue)
     assert float(d) == 2.0
 
+
 def test_int_division(self):
     # UFL treats all divisions as true division
     d = as_ufl(40) / 7
     self.assertIsInstance(d, FloatValue)
     assert float(d) == 40.0 / 7.0
-    #self.assertAlmostEqual(float(d), 40 / 7.0, 15)
+    # self.assertAlmostEqual(float(d), 40 / 7.0, 15)
+
 
 def test_float_int_division(self):
     d = as_ufl(20.0) / 5
     self.assertIsInstance(d, FloatValue)
     assert float(d) == 4.0
 
+
 def test_floor_division_fails(self):
     f = as_ufl(2.0)
     r = as_ufl(4)
@@ -47,6 +54,7 @@ def test_floor_division_fails(self):
     self.assertRaises(NotImplementedError, lambda: r // s)
     self.assertRaises(NotImplementedError, lambda: f // s)
 
+
 def test_elem_mult(self):
     self.assertEqual(int(elem_mult(2, 3)), 6)
 
@@ -54,6 +62,7 @@ def test_elem_mult(self):
     u = as_vector((4, 5, 6))
     self.assertEqual(elem_mult(v, u), as_vector((4, 10, 18)))
 
+
 def test_elem_mult_on_matrices(self):
     A = as_matrix(((1, 2), (3, 4)))
     B = as_matrix(((4, 5), (6, 7)))
@@ -69,12 +78,14 @@ def test_elem_mult_on_matrices(self):
     B = Identity(2)
     self.assertEqual(elem_mult(A, B), as_matrix(((x, 0), (0, 4))))
 
+
 def test_elem_div(self):
     x, y, z = SpatialCoordinate(tetrahedron)
     A = as_matrix(((x, y, z), (3, 4, 5)))
     B = as_matrix(((7, 8, 9), (z, x, y)))
     self.assertEqual(elem_div(A, B), as_matrix(((x/7, y/8, z/9), (3/z, 4/x, 5/y))))
 
+
 def test_elem_op(self):
     x, y, z = SpatialCoordinate(tetrahedron)
     A = as_matrix(((x, y, z), (3, 4, 5)))
diff --git a/test/test_automatic_differentiation.py b/test/test_automatic_differentiation.py
index 2aba149..0b326c1 100755
--- a/test/test_automatic_differentiation.py
+++ b/test/test_automatic_differentiation.py
@@ -22,7 +22,9 @@ from ufl.corealg.traversal import unique_post_traversal
 from ufl.conditional import Conditional
 from ufl.algorithms import expand_derivatives
 
+
 class ExpressionCollection(object):
+
     def __init__(self, cell):
         self.cell = cell
 
@@ -32,7 +34,7 @@ class ExpressionCollection(object):
         c = CellVolume(cell)
         h = Circumradius(cell)
         f = FacetArea(cell)
-        #s = CellSurfaceArea(cell)
+        # s = CellSurfaceArea(cell)
         # FIXME: Add all new geometry types here!
 
         I = Identity(d)
@@ -69,16 +71,16 @@ class ExpressionCollection(object):
             u+2*u, v+2*v, w+2*w,
             2/u, u/2, v/2, w/2,
             u**3, 3**u,
-            ])
+        ])
         self.mathfunctions = ([
             abs(u), sqrt(u), exp(u), ln(u),
             cos(u), sin(u), tan(u), acos(u), asin(u), atan(u),
             erf(u), bessel_I(1, u), bessel_J(1, u), bessel_K(1, u), bessel_Y(1, u),
-            ])
+        ])
         self.variables = ([
             variable(u), variable(v), variable(w),
             variable(w*u), 3*variable(w*u),
-            ])
+        ])
 
         if d == 1:
             w2 = as_matrix(((u**2,),))
@@ -107,7 +109,7 @@ class ExpressionCollection(object):
                 as_matrix(((u**2, u**3), (u**4, u**5))),
                 as_vector((u, 2, 3))[i],
                 w2[i, j]*w[i, j],
-                ])
+        ])
         self.conditionals = ([
             conditional(le(u, 1.0), 1, 0),
             conditional(eq(3.0, u), 1, 0),
@@ -122,7 +124,7 @@ class ExpressionCollection(object):
             conditional(Not(ge(u, 0.0)), 1, 2),
             conditional(And(Not(ge(u, 0.0)), lt(u, 1.0)), 1, 2),
             conditional(le(u, 0.0), u**3, ln(u)),
-            ])
+        ])
         self.restrictions = [u('+'), u('-'), v('+'), v('-'), w('+'), w('-')]
         if d > 1:
             i, j = indices(2)
@@ -131,7 +133,7 @@ class ExpressionCollection(object):
                 v[i]('+')*v[i]('+'),
                 (v[i]*v[i])('+'),
                 (v[i]*v[j])('+')*w[i, j]('+'),
-                ])
+            ])
 
         self.noncompounds = []
         self.noncompounds += self.algebra
@@ -154,7 +156,7 @@ class ExpressionCollection(object):
                 outer(w, v),
                 outer(v, w),
                 outer(w, w),
-                ])
+            ])
 
         if d == 1:
             self.tensoralgebra = []
@@ -162,7 +164,7 @@ class ExpressionCollection(object):
             self.tensoralgebra = ([
                 w.T, sym(w), skew(w), dev(w),
                 det(w), tr(w), cofac(w), inv(w),
-                ])
+            ])
 
         if d != 3:
             self.crossproducts = []
@@ -173,7 +175,7 @@ class ExpressionCollection(object):
                 cross(v, w[0,:]),
                 cross(v, w[:, 1]),
                 cross(w[:, 0], v),
-                ])
+            ])
 
         self.compounds = []
         self.compounds += self.tensorproducts
@@ -185,17 +187,19 @@ class ExpressionCollection(object):
         self.all_expressions += self.noncompounds
         self.all_expressions += self.compounds
 
- at pytest.fixture(params=(1,2,3))
+
+ at pytest.fixture(params=(1, 2, 3))
 def d_expr(request):
     d = request.param
-    cell = { 1: interval, 2: triangle, 3: tetrahedron }[d]
+    cell = {1: interval, 2: triangle, 3: tetrahedron}[d]
     expr = ExpressionCollection(cell)
     return d, expr
 
+
 def ad_algorithm(expr):
-    #alt = 1
-    #alt = 4
-    #alt = 6
+    # alt = 1
+    # alt = 4
+    # alt = 6
     alt = 0
     if alt == 0:
         return expand_derivatives(expr)
@@ -225,40 +229,47 @@ def ad_algorithm(expr):
             apply_expand_compounds_after=False,
             use_alternative_wrapper_algorithm=False)
 
+
 def _test_no_derivatives_no_change(self, collection):
     for expr in collection:
         before = expr
         after = ad_algorithm(before)
-        #print '\n', str(before), '\n', str(after), '\n'
+        # print '\n', str(before), '\n', str(after), '\n'
         self.assertEqualTotalShape(before, after)
         assert before == after
 
+
 def _test_no_derivatives_but_still_changed(self, collection):
     # Planning to fix these:
     for expr in collection:
         before = expr
         after = ad_algorithm(before)
-        #print '\n', str(before), '\n', str(after), '\n'
+        # print '\n', str(before), '\n', str(after), '\n'
         self.assertEqualTotalShape(before, after)
-        #assert before == after # Without expand_compounds
+        # assert before == after # Without expand_compounds
         self.assertNotEqual(before, after) # With expand_compounds
 
+
 def test_only_terminals_no_change(self, d_expr):
     d, ex = d_expr
     _test_no_derivatives_no_change(self, ex.terminals)
 
+
 def test_no_derivatives_no_change(self, d_expr):
     d, ex = d_expr
     _test_no_derivatives_no_change(self, ex.noncompounds)
 
+
 def xtest_compounds_no_derivatives_no_change(self, d_expr): # This test fails with expand_compounds enabled
     d, ex = d_expr
     _test_no_derivatives_no_change(self, ex.compounds)
 
+
 def test_zero_derivatives_of_terminals_produce_the_right_types_and_shapes(self, d_expr):
     d, ex = d_expr
     _test_zero_derivatives_of_terminals_produce_the_right_types_and_shapes(self, ex)
 
+
 def _test_zero_derivatives_of_terminals_produce_the_right_types_and_shapes(self, collection):
     c = Constant(collection.shared_objects.cell)
 
@@ -271,19 +282,21 @@ def _test_zero_derivatives_of_terminals_produce_the_right_types_and_shapes(self,
             before = derivative(t, var) # This will often get preliminary simplified to zero
             after = ad_algorithm(before)
             expected = 0*t
-            #print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
+            # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
             before = derivative(c*t, var) # This will usually not get simplified to zero
             after = ad_algorithm(before)
             expected = 0*t
-            #print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
+            # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
+
 def test_zero_diffs_of_terminals_produce_the_right_types_and_shapes(self, d_expr):
     d, ex = d_expr
     _test_zero_diffs_of_terminals_produce_the_right_types_and_shapes(self, ex)
 
+
 def _test_zero_diffs_of_terminals_produce_the_right_types_and_shapes(self, collection):
     c = Constant(collection.shared_objects.cell)
 
@@ -299,19 +312,21 @@ def _test_zero_diffs_of_terminals_produce_the_right_types_and_shapes(self, colle
             before = diff(t, var) # This will often get preliminary simplified to zero
             after = ad_algorithm(before)
             expected = 0*outer(t, var)
-            #print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
+            # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
             before = diff(c*t, var) # This will usually not get simplified to zero
             after = ad_algorithm(before)
             expected = 0*outer(t, var)
-            #print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
+            # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
+
 def test_zero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(self, d_expr):
     d, ex = d_expr
     _test_zero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(self, ex)
 
+
 def _test_zero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(self, collection):
     debug = 0
 
@@ -319,26 +334,35 @@ def _test_zero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(se
     v = Coefficient(collection.shared_objects.V)
     w = Coefficient(collection.shared_objects.W)
 
-    #for t in chain(collection.noncompounds, collection.compounds):
-    #debug = True
+    # for t in chain(collection.noncompounds, collection.compounds):
+    # debug = True
     for t in collection.noncompounds:
         for var in (u, v, w):
-            if debug: print('\n', 'shapes:   ', t.ufl_shape, var.ufl_shape, '\n')
-            if debug: print('\n', 't:        ', str(t), '\n')
-            if debug: print('\n', 't ind:    ', str(t.ufl_free_indices), '\n')
-            if debug: print('\n', 'var:      ', str(var), '\n')
+            if debug:
+                print('\n', 'shapes:   ', t.ufl_shape, var.ufl_shape, '\n')
+            if debug:
+                print('\n', 't:        ', str(t), '\n')
+            if debug:
+                print('\n', 't ind:    ', str(t.ufl_free_indices), '\n')
+            if debug:
+                print('\n', 'var:      ', str(var), '\n')
             before = derivative(t, var)
-            if debug: print('\n', 'before:   ', str(before), '\n')
+            if debug:
+                print('\n', 'before:   ', str(before), '\n')
             after = ad_algorithm(before)
-            if debug: print('\n', 'after:    ', str(after), '\n')
+            if debug:
+                print('\n', 'after:    ', str(after), '\n')
             expected = 0*t
-            if debug: print('\n', 'expected: ', str(expected), '\n')
+            if debug:
+                print('\n', 'expected: ', str(expected), '\n')
             assert after == expected
 
+
 def test_zero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, d_expr):
     d, ex = d_expr
     _test_zero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, ex)
 
+
 def _test_zero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, collection):
     debug = 0
 
@@ -350,22 +374,27 @@ def _test_zero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, co
     vv = variable(v)
     vw = variable(w)
 
-    #for t in chain(collection.noncompounds, collection.compounds):
+    # for t in chain(collection.noncompounds, collection.compounds):
     for t in collection.noncompounds:
         for var in (vu, vv, vw):
             before = diff(t, var)
-            if debug: print('\n', 'before:   ', str(before), '\n')
+            if debug:
+                print('\n', 'before:   ', str(before), '\n')
             after = ad_algorithm(before)
-            if debug: print('\n', 'after:    ', str(after), '\n')
+            if debug:
+                print('\n', 'after:    ', str(after), '\n')
             expected = 0*outer(t, var)
-            if debug: print('\n', 'expected: ', str(expected), '\n')
-            #print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
+            if debug:
+                print('\n', 'expected: ', str(expected), '\n')
+            # print '\n', str(expected), '\n', str(after), '\n', str(before), '\n'
             assert after == expected
 
+
 def test_nonzero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(self, d_expr):
     d, ex = d_expr
     _test_nonzero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(self, ex)
 
+
 def _test_nonzero_derivatives_of_noncompounds_produce_the_right_types_and_shapes(self, collection):
     debug = 0
 
@@ -373,22 +402,27 @@ def _test_nonzero_derivatives_of_noncompounds_produce_the_right_types_and_shapes
     v = collection.shared_objects.v
     w = collection.shared_objects.w
 
-    #for t in chain(collection.noncompounds, collection.compounds):
+    # for t in chain(collection.noncompounds, collection.compounds):
     for t in collection.noncompounds:
         for var in (u, v, w):
             # Include d/dx [z ? y: x] but not d/dx [x ? f: z]
             if isinstance(t, Conditional) and (var in unique_post_traversal(t.ufl_operands[0])):
-                if debug: print(("Depends on %s :: %s" % (str(var), str(t))))
+                if debug:
+                    print(("Depends on %s :: %s" % (str(var), str(t))))
                 continue
 
-            if debug: print(('\n', '...:   ', t.ufl_shape, var.ufl_shape, '\n'))
+            if debug:
+                print(('\n', '...:   ', t.ufl_shape, var.ufl_shape, '\n'))
             before = derivative(t, var)
-            if debug: print(('\n', 'before:   ', str(before), '\n'))
+            if debug:
+                print(('\n', 'before:   ', str(before), '\n'))
             after = ad_algorithm(before)
-            if debug: print(('\n', 'after:    ', str(after), '\n'))
+            if debug:
+                print(('\n', 'after:    ', str(after), '\n'))
             expected_shape = 0*t
-            if debug: print(('\n', 'expected_shape: ', str(expected_shape), '\n'))
-            #print '\n', str(expected_shape), '\n', str(after), '\n', str(before), '\n'
+            if debug:
+                print(('\n', 'expected_shape: ', str(expected_shape), '\n'))
+            # print '\n', str(expected_shape), '\n', str(after), '\n', str(before), '\n'
 
             if var in unique_post_traversal(t):
                 self.assertEqualTotalShape(after, expected_shape)
@@ -396,10 +430,12 @@ def _test_nonzero_derivatives_of_noncompounds_produce_the_right_types_and_shapes
             else:
                 assert after == expected_shape
 
+
 def test_nonzero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, d_expr):
     d, ex = d_expr
     _test_nonzero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, ex)
 
+
 def _test_nonzero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self, collection):
     debug = 0
     u = collection.shared_objects.u
@@ -410,22 +446,26 @@ def _test_nonzero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self,
     vv = variable(v)
     vw = variable(w)
 
-    #for t in chain(collection.noncompounds, collection.compounds):
+    # for t in chain(collection.noncompounds, collection.compounds):
     for t in collection.noncompounds:
         t = replace(t, {u:vu, v:vv, w:vw})
         for var in (vu, vv, vw):
             # Include d/dx [z ? y: x] but not d/dx [x ? f: z]
             if isinstance(t, Conditional) and (var in unique_post_traversal(t.ufl_operands[0])):
-                if debug: print(("Depends on %s :: %s" % (str(var), str(t))))
+                if debug:
+                    print(("Depends on %s :: %s" % (str(var), str(t))))
                 continue
 
             before = diff(t, var)
-            if debug: print(('\n', 'before:   ', str(before), '\n'))
+            if debug:
+                print(('\n', 'before:   ', str(before), '\n'))
             after = ad_algorithm(before)
-            if debug: print(('\n', 'after:    ', str(after), '\n'))
+            if debug:
+                print(('\n', 'after:    ', str(after), '\n'))
             expected_shape = 0*outer(t, var) # expected shape, not necessarily value
-            if debug: print(('\n', 'expected_shape: ', str(expected_shape), '\n'))
-            #print '\n', str(expected_shape), '\n', str(after), '\n', str(before), '\n'
+            if debug:
+                print(('\n', 'expected_shape: ', str(expected_shape), '\n'))
+            # print '\n', str(expected_shape), '\n', str(after), '\n', str(before), '\n'
 
             if var in unique_post_traversal(t):
                 self.assertEqualTotalShape(after, expected_shape)
@@ -433,6 +473,7 @@ def _test_nonzero_diffs_of_noncompounds_produce_the_right_types_and_shapes(self,
             else:
                 assert after == expected_shape
 
+
 def test_grad_coeff(self, d_expr):
     d, collection = d_expr
 
@@ -454,12 +495,13 @@ def test_grad_coeff(self, d_expr):
         before = grad(grad(f))
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert before == after # Differing by being wrapped in indexing types
+        # assert before == after # Differing by being wrapped in indexing types
 
         before = grad(grad(grad(f)))
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert before == after # Differing by being wrapped in indexing types
+        # assert before == after # Differing by being wrapped in indexing types
+
 
 def test_derivative_grad_coeff(self, d_expr):
     d, collection = d_expr
@@ -471,22 +513,23 @@ def test_derivative_grad_coeff(self, d_expr):
         before = derivative(grad(f), f)
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert after == expected
+        # assert after == expected
 
         before = derivative(grad(grad(f)), f)
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert after == expected
+        # assert after == expected
 
         before = derivative(grad(grad(grad(f))), f)
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert after == expected
+        # assert after == expected
         if 0:
             print()
             print(('B', f, "::", before))
             print(('A', f, "::", after))
 
+
 def xtest_derivative_grad_coeff_with_variation_components(self, d_expr):
     d, collection = d_expr
 
@@ -503,17 +546,17 @@ def xtest_derivative_grad_coeff_with_variation_components(self, d_expr):
         before = derivative(grad(g), f, df)
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert after == expected
+        # assert after == expected
 
         before = derivative(grad(grad(g)), f, df)
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert after == expected
+        # assert after == expected
 
         before = derivative(grad(grad(grad(g))), f, df)
         after = ad_algorithm(before)
         self.assertEqualTotalShape(before, after)
-        #assert after == expected
+        # assert after == expected
         if 0:
             print()
             print(('B', f, "::", before))
diff --git a/test/test_book_snippets.py b/test/test_book_snippets.py
index f5bb316..a740014 100755
--- a/test/test_book_snippets.py
+++ b/test/test_book_snippets.py
@@ -13,6 +13,7 @@ import pytest
 from ufl import *
 from ufl.algorithms import *
 
+
 def test_uflcode_269(self):
     # Finite element spaces
     cell = tetrahedron
@@ -44,13 +45,16 @@ def test_uflcode_269(self):
     L = inner(F*S, grad(phi0))*dx
     a = derivative(L, u, phi1)
 
+
 def test_uflcode_316(self):
     shapestring = 'triangle'
     cell = Cell(shapestring)
 
+
 def test_uflcode_323(self):
     cell = tetrahedron
 
+
 def test_uflcode_356(self):
     cell = tetrahedron
 
@@ -61,6 +65,7 @@ def test_uflcode_356(self):
     TH = V*P
     ME = MixedElement(T, V, P)
 
+
 def test_uflcode_400(self):
     V = FiniteElement("CG", triangle, 1)
     f = Coefficient(V)
@@ -73,6 +78,7 @@ def test_uflcode_400(self):
     a = w*dot(grad(u), grad(v))*dx
     L = f*v*dx + g**2*v*ds(0) + h*v*ds(1)
 
+
 def test_uflcode_469(self):
     V = FiniteElement("CG", triangle, 1)
     f = Coefficient(V)
@@ -80,11 +86,12 @@ def test_uflcode_469(self):
     h = Coefficient(V)
     v = TestFunction(V)
     # ...
-    dx02 = dx(0, { "integration_order": 2 })
-    dx14 = dx(1, { "integration_order": 4 })
-    dx12 = dx(1, { "integration_order": 2 })
+    dx02 = dx(0, {"integration_order": 2})
+    dx14 = dx(1, {"integration_order": 4})
+    dx12 = dx(1, {"integration_order": 2})
     L = f*v*dx02 + g*v*dx14 + h*v*dx12
 
+
 def test_uflcode_552(self):
     element = FiniteElement("CG", triangle, 1)
     # ...
@@ -92,6 +99,7 @@ def test_uflcode_552(self):
     v = TestFunction(element)
     u = TrialFunction(element)
 
+
 def test_uflcode_563(self):
     cell = triangle
     element = FiniteElement("CG", cell, 1)
@@ -101,6 +109,7 @@ def test_uflcode_563(self):
     v = VectorConstant(cell)
     M = TensorConstant(cell)
 
+
 def test_uflcode_574(self):
     V0 = FiniteElement("CG", triangle, 1)
     V1 = V0
@@ -109,6 +118,7 @@ def test_uflcode_574(self):
     u = Coefficient(V)
     u0, u1 = split(u)
 
+
 def test_uflcode_582(self):
     V0 = FiniteElement("CG", triangle, 1)
     V1 = V0
@@ -121,6 +131,7 @@ def test_uflcode_582(self):
     u0, u1 = TrialFunctions(V)
     f0, f1 = Coefficients(V)
 
+
 def test_uflcode_644(self):
     V = VectorElement("CG", triangle, 1)
     u = Coefficient(V)
@@ -129,6 +140,7 @@ def test_uflcode_644(self):
     A = outer(u, v)
     Aij = A[i, j]
 
+
 def test_uflcode_651(self):
     V = VectorElement("CG", triangle, 1)
     u = Coefficient(V)
@@ -137,19 +149,22 @@ def test_uflcode_651(self):
     Aij = v[j]*u[i]
     A = as_tensor(Aij, (i, j))
 
+
 def test_uflcode_671(self):
     i = Index()
     j, k, l = indices(3)
 
+
 def test_uflcode_684(self):
     V = VectorElement("CG", triangle, 1)
     v = Coefficient(V)
     # ...
     th = pi/2
-    A = as_matrix([[ cos(th), -sin(th)],
-                   [ sin(th),  cos(th)]])
+    A = as_matrix([[cos(th), -sin(th)],
+                   [sin(th), cos(th)]])
     u = A*v
 
+
 def test_uflcode_824(self):
     V = VectorElement("CG", triangle, 1)
     f = Coefficient(V)
@@ -157,25 +172,28 @@ def test_uflcode_824(self):
     df = Dx(f, i)
     df = f.dx(i)
 
+
 def test_uflcode_886(self):
     cell = triangle
     # ...
-    x = SpatialCoordinate(cell) # Original: x = cell.x
+    x = SpatialCoordinate(cell)  # Original: x = cell.x
     g = sin(x[0])
     v = variable(g)
     f = exp(v**2)
     h = diff(f, v)
     # ...
-    #print v
-    #print h
+    # print v
+    # print h
+
 
 def test_python_894(self):
     # We don't have to keep the string output compatible, so no test here.
     pass
     #>>> print v
-    #var0(sin((x)[0]))
+    # var0(sin((x)[0]))
     #>>> print h
-    #d/d[var0(sin((x)[0]))] (exp((var0(sin((x)[0]))) ** 2))
+    # d/d[var0(sin((x)[0]))] (exp((var0(sin((x)[0]))) ** 2))
+
 
 def test_uflcode_930(self):
     condition = lt(1, 0)
@@ -184,11 +202,13 @@ def test_uflcode_930(self):
     # ...
     f = conditional(condition, true_value, false_value)
 
+
 def test_uflcode_1003(self):
     # Not testable, but this is tested below anyway
     "a = derivative(L, w, u)"
     pass
 
+
 def test_uflcode_1026(self):
     element = FiniteElement("CG", triangle, 1)
     # ...
@@ -199,6 +219,7 @@ def test_uflcode_1026(self):
     F = derivative(f, w, v)
     J = derivative(F, w, u)
 
+
 def test_uflcode_1050(self):
     Vx = VectorElement("Lagrange", triangle, 1)
     Vy = FiniteElement("Lagrange", triangle, 1)
@@ -208,6 +229,7 @@ def test_uflcode_1050(self):
     F = derivative(f, u)
     J = derivative(F, u)
 
+
 def test_uflcode_1085(self):
     cell = triangle
     # ...
@@ -219,6 +241,7 @@ def test_uflcode_1085(self):
     a = M[i, j]*u[k].dx(j)*v[k].dx(i)*dx
     astar = adjoint(a)
 
+
 def test_uflcode_1120(self):
     cell = triangle
     # ...
@@ -227,9 +250,10 @@ def test_uflcode_1120(self):
     f = Coefficient(V)
     g = Coefficient(V)
     L = f**2 / (2*g)*v*dx
-    L2 = replace(L, { f: g, g: 3})
+    L2 = replace(L, {f: g, g: 3})
     L3 = g**2 / 6*v*dx
 
+
 def test_uflcode_1157(self):
     cell = triangle
     # ...
@@ -240,6 +264,7 @@ def test_uflcode_1157(self):
     pde = u*v*dx - f*v*dx
     a, L = system(pde)
 
+
 def test_uflcode_1190(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1)
@@ -254,6 +279,7 @@ def test_uflcode_1190(self):
     u = Coefficient(element)
     sL = diff(L, c) - action(diff(a, c), u)
 
+
 def test_uflcode_1195(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1)
@@ -268,18 +294,21 @@ def test_uflcode_1195(self):
     # ...
     sL = sensitivity_rhs(a, u, L, c)
 
+
 def test_uflcode_1365(self):
     e = 0
     v = variable(e)
     f = sin(v)
     g = diff(f, v)
 
+
 def test_python_1426(self):
     # Covered by the below test
     pass
-    #from ufl.algorithms import Graph
-    #G = Graph(expression)
-    #V, E = G
+    # from ufl.algorithms import Graph
+    # G = Graph(expression)
+    # V, E = G
+
 
 def test_python_1446(self):
     cell = triangle
@@ -291,13 +320,14 @@ def test_python_1446(self):
     e = c*f**2*u*v
 
     # The linearized Graph functionality has been removed from UFL:
-    #from ufl.algorithms import Graph, partition
-    #G = Graph(e)
-    #V, E, = G
+    # from ufl.algorithms import Graph, partition
+    # G = Graph(e)
+    # V, E, = G
+
+    # print(("str(e) = %s\n" % str(e)))
+    # print(("\n".join("V[%d] = %s" % (i, v) for (i, v) in enumerate(V)), "\n"))
+    # print(("\n".join("E[%d] = %s" % (i, e) for (i, e) in enumerate(E)), "\n"))
 
-    #print(("str(e) = %s\n" % str(e)))
-    #print(("\n".join("V[%d] = %s" % (i, v) for (i, v) in enumerate(V)), "\n"))
-    #print(("\n".join("E[%d] = %s" % (i, e) for (i, e) in enumerate(E)), "\n"))
 
 def test_python_1512(self):
     cell = triangle
@@ -309,12 +339,13 @@ def test_python_1512(self):
     e = c*f**2*u*v
 
     # The linearized Graph functionality has been removed from UFL:
-    #from ufl.algorithms import Graph, partition
-    #G = Graph(e)
-    #V, E, = G
+    # from ufl.algorithms import Graph, partition
+    # G = Graph(e)
+    # V, E, = G
     # ...
-    #Vin = G.Vin()
-    #Vout = G.Vout()
+    # Vin = G.Vin()
+    # Vout = G.Vout()
+
 
 def test_python_1557(self):
     cell = triangle
@@ -326,19 +357,20 @@ def test_python_1557(self):
     e = c*f**2*u*v
 
     # The linearized Graph functionality has been removed from UFL:
-    #from ufl.algorithms import Graph, partition
-    #G = Graph(e)
-    #V, E, = G
+    # from ufl.algorithms import Graph, partition
+    # G = Graph(e)
+    # V, E, = G
     # ...
-    #partitions, keys = partition(G)
-    #for deps in sorted(partitions.keys()):
+    # partitions, keys = partition(G)
+    # for deps in sorted(partitions.keys()):
     #    P = partitions[deps]
-    #    #print "The following depends on", tuple(deps)
+    # print "The following depends on", tuple(deps)
     #    for i in sorted(P):
-    #        #print "V[%d] = %s" % (i, V[i])
-    #        # ...
+    # print "V[%d] = %s" % (i, V[i])
+    # ...
     #        v = V[i]
 
+
 def test_python_1843(self):
     def apply_ad(e, ad_routine):
         if e._ufl_is_terminal_:
@@ -349,6 +381,7 @@ def test_python_1843(self):
             e = ad_routine(e)
         return e
 
+
 def test_uflcode_1901(self):
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1)
@@ -356,6 +389,7 @@ def test_uflcode_1901(self):
     v = Argument(element, 2)
     w = Coefficient(element)
 
+
 def test_python_1942(self):
     def walk(expression, pre_action, post_action):
         pre_action(expression)
@@ -363,15 +397,17 @@ def test_python_1942(self):
             walk(o)
         post_action(expression)
 
+
 def test_python_1955(self):
     def post_traversal(root):
         for o in root.ufl_operands:
             yield post_traversal(o)
         yield root
 
+
 def test_python_1963(self):
     def post_action(e):
-        #print str(e)
+        # print str(e)
         pass
     cell = triangle
     V = FiniteElement("Lagrange", cell, 1)
@@ -384,9 +420,11 @@ def test_python_1963(self):
     for e in post_traversal(expression):
         post_action(e)
 
+
 def test_python_1990(self):
     from ufl.classes import IntValue, Sum
     expression = as_ufl(3)
+
     def int_operation(x):
         return 7
     # ...
@@ -398,8 +436,10 @@ def test_python_1990(self):
     # ...
     self.assertTrue(result == 7)
 
+
 def test_python_2024(self):
     class ExampleFunction(MultiFunction):
+
         def __init__(self):
             MultiFunction.__init__(self)
 
@@ -419,20 +459,23 @@ def test_python_2024(self):
 
     cell = triangle
     element = FiniteElement("Lagrange", cell, 1)
-    x = SpatialCoordinate(cell) # Original: x = cell.x
+    x = SpatialCoordinate(cell)  # Original: x = cell.x
     if 0:
         print((m(Argument(element, 2))))
         print((m(x)))
         print((m(x[0] + x[1])))
         print((m(x[0] * x[1])))
 
+
 def test_python_2066(self):
     def apply(e, multifunction):
         ops = [apply(o, multifunction) for o in e.ufl_operands]
         return multifunction(e, *ops)
 
+
 def test_python_2087(self):
     class Replacer(Transformer):
+
         def __init__(self, mapping):
             Transformer.__init__(self)
             self.mapping = mapping
@@ -447,6 +490,7 @@ def test_python_2087(self):
     r = Replacer({f: f**2})
     g = r.visit(2*f)
 
+
 def test_python_2189(self):
     V = FiniteElement("Lagrange", triangle, 1)
     u = TestFunction(V)
@@ -466,51 +510,61 @@ def test_python_2189(self):
     aif = tree_format(ai)
 
     if 0:
-        print(("\na: ", str(a),  "\n", tree_format(a)))
+        print(("\na: ", str(a), "\n", tree_format(a)))
         print(("\nac:", str(ac), "\n", tree_format(ac)))
         print(("\nad:", str(ad), "\n", tree_format(ad)))
         print(("\nai:", str(ai), "\n", tree_format(ai)))
 
+
 def test_python_2328(self):
     cell = triangle
-    x = SpatialCoordinate(cell) # Original: x = cell.x
+    x = SpatialCoordinate(cell)  # Original: x = cell.x
     e = x[0] + x[1]
-    #print e((0.5, 0.7)) # prints 1.2
+    # print e((0.5, 0.7)) # prints 1.2
     # ...
-    self.assertEqual( e((0.5, 0.7)), 1.2 )
+    self.assertEqual(e((0.5, 0.7)), 1.2)
+
 
 def test_python_2338(self):
     cell = triangle
-    x = SpatialCoordinate(cell) # Original: x = cell.x
+    x = SpatialCoordinate(cell)  # Original: x = cell.x
     # ...
     c = Constant(cell)
     e = c*(x[0] + x[1])
-    #print e((0.5, 0.7), { c: 10 }) # prints 12.0
+    # print e((0.5, 0.7), { c: 10 }) # prints 12.0
     # ...
-    self.assertEqual( e((0.5, 0.7), { c: 10 }), 12.0 )
+    self.assertEqual(e((0.5, 0.7), {c: 10}), 12.0)
+
 
 def test_python_2349(self):
     element = VectorElement("Lagrange", triangle, 1)
     c = Constant(triangle)
     f = Coefficient(element)
     e = c*(f[0] + f[1])
+
     def fh(x):
         return (x[0], x[1])
-    #print e((0.5, 0.7), { c: 10, f: fh }) # prints 12.0
+    # print e((0.5, 0.7), { c: 10, f: fh }) # prints 12.0
     # ...
-    self.assertEqual( e((0.5, 0.7), { c: 10, f: fh }), 12.0 )
+    self.assertEqual(e((0.5, 0.7), {c: 10, f: fh}), 12.0)
+
 
 def test_python_2364(self):
     element = FiniteElement("Lagrange", triangle, 1)
     g = Coefficient(element)
     e = g**2 + g.dx(0)**2 + g.dx(1)**2
+
     def gh(x, der=()):
-        if der == ():   return x[0]*x[1]
-        if der == (0,): return x[1]
-        if der == (1,): return x[0]
-    #print e((2, 3), { g: gh }) # prints 49
+        if der == ():
+            return x[0]*x[1]
+        if der == (0,):
+            return x[1]
+        if der == (1,):
+            return x[0]
+    # print e((2, 3), { g: gh }) # prints 49
     # ...
-    self.assertEqual( e((2, 3), { g: gh }), 49 )
+    self.assertEqual(e((2, 3), {g: gh}), 49)
+
 
 def test_python_2462(self):
     cell = triangle
@@ -525,6 +579,6 @@ def test_python_2462(self):
     u = Coefficient(element)
     myform = a
     # ...
-    #print repr(preprocess(myform).preprocessed_form)
+    # print repr(preprocess(myform).preprocessed_form)
     # ...
     r = repr(compute_form_data(myform).preprocessed_form)
diff --git a/test/test_change_to_reference_frame.py b/test/test_change_to_reference_frame.py
index df3b4cf..64d4cd5 100755
--- a/test/test_change_to_reference_frame.py
+++ b/test/test_change_to_reference_frame.py
@@ -15,7 +15,6 @@ from ufl.algorithms import tree_format, change_to_reference_grad
 from six.moves import xrange as range
 
 from ufl.log import error, warning
-from ufl.assertions import ufl_assert
 
 from ufl.core.multiindex import Index, indices
 from ufl.corealg.multifunction import MultiFunction
@@ -40,12 +39,12 @@ from ufl.permutation import compute_indices
 
 from ufl.algorithms.transformer import ReuseTransformer, apply_transformer
 from ufl.compound_expressions import determinant_expr, cross_expr, inverse_expr
-from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, OuterProductElement, OuterProductVectorElement, TensorElement, FacetElement, InteriorElement, BrokenElement, TraceElement
+from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, TensorProductElement, TensorElement, FacetElement, InteriorElement, BrokenElement.
 '''
 
 
 def change_integral_to_reference_frame(form, context):
-    if False: # TODO: integral.is_in_reference_frame():
+    if False:  # TODO: integral.is_in_reference_frame():
         # TODO: Assume reference frame integral is written purely in
         #       reference frame or tramsform integrand here as well?
         return integrand
@@ -57,7 +56,7 @@ def change_integral_to_reference_frame(form, context):
         scale = compute_integrand_scaling_factor(integral.ufl_domain(),
                                                  integral.integral_type())
 
-        return integral.reconstruct(integrand * scale) # TODO: , reference=True)
+        return integral.reconstruct(integrand * scale)  # TODO: , reference=True)
 
 
 def change_expr_to_reference_frame(expr):
@@ -176,6 +175,7 @@ def test_change_hcurl_form_arguments_to_reference_frame():
     m = e | indexed(e)                   # scalar component of
     '''
 
+
 def new_analyse_modified_terminal(expr):
     assert expr._ufl_is_terminal_ or expr._ufl_is_terminal_modifier_type_
     m = expr
@@ -190,7 +190,7 @@ def new_analyse_modified_terminal(expr):
 
     # The evaluation mode is one of current point,
     # a cell entity midpoint, or averaging over a cell entity
-    if unindexed._ufl_is_evaluation_type_: # averages and point evaluations
+    if unindexed._ufl_is_evaluation_type_:  # averages and point evaluations
         v, = v.ufl_operand
         evaluation = unindexed.ufl_handler_name
     else:
@@ -247,13 +247,13 @@ def new_analyse_modified_terminal(expr):
     # Apply paranoid dimension checking
     assert len(indices) == len(unindexed_shape)
     assert all(0 <= i for i in indices)
-    assert all(i < j for i,j in zip(indices, unindexed_shape))
+    assert all(i < j for i, j in zip(indices, unindexed_shape))
     assert len(core_indices) == len(core_shape)
     assert all(0 <= i for i in core_indices)
-    assert all(i < j for i,j in zip(core_indices, core_shape))
-    assert len(derivative_indices) == len(derivatives_shape) # This will fail for e.g. div(grad(f))
+    assert all(i < j for i, j in zip(core_indices, core_shape))
+    assert len(derivative_indices) == len(derivatives_shape)  # This will fail for e.g. div(grad(f))
     assert all(0 <= i for i in derivative_indices)
-    assert all(i < j for i,j in zip(derivative_indices, derivatives_shape))
+    assert all(i < j for i, j in zip(derivative_indices, derivatives_shape))
 
     # Return values:
     mt = ModifiedTerminal(
@@ -266,7 +266,7 @@ def new_analyse_modified_terminal(expr):
         derivatives,
         restriction,
         terminal
-        )
+    )
     return mt
 
 
diff --git a/test/test_check_arities.py b/test/test_check_arities.py
index e2bfb46..654ede5 100755
--- a/test/test_check_arities.py
+++ b/test/test_check_arities.py
@@ -4,6 +4,7 @@ import pytest
 from ufl import *
 from ufl.algorithms.compute_form_data import compute_form_data
 
+
 def test_check_arities():
     # Code from bitbucket issue #49
     cell = tetrahedron
diff --git a/test/test_classcoverage.py b/test/test_classcoverage.py
index 5115bc2..f4c4779 100755
--- a/test/test_classcoverage.py
+++ b/test/test_classcoverage.py
@@ -16,6 +16,8 @@ from ufl.algorithms import *
 
 has_repr = set()
 has_dict = set()
+
+
 def _test_object(a, shape, free_indices):
     # Check if instances of this type has certain memory consuming members
     if hasattr(a, '_repr'):
@@ -50,6 +52,7 @@ def _test_object(a, shape, free_indices):
             print(("shape:", shape))
         assert sh == shape
 
+
 def _test_object2(a):
     # Check if instances of this type has certain memory consuming members
     if hasattr(a, '_repr'):
@@ -65,6 +68,7 @@ def _test_object2(a):
     # Can't really test str more than that it exists
     s = str(a)
 
+
 def _test_form(a):
     # Test reproduction via repr string
     r = repr(a)
@@ -90,6 +94,7 @@ def testExports(self):
         print(("\n".join(sorted(missing_classes))))
     assert missing_classes == set()
 
+
 def testAll(self):
 
     Expr.ufl_enable_profiling()
@@ -162,9 +167,9 @@ def testAll(self):
     xi = CellCoordinate(cell)
     _test_object(xi, (dim,), ())
 
-    #g = CellBarycenter(cell)
+    # g = CellBarycenter(cell)
     #_test_object(g, (dim,), ())
-    #g = FacetBarycenter(cell)
+    # g = FacetBarycenter(cell)
     #_test_object(g, (dim,), ())
 
     g = Jacobian(cell)
@@ -183,14 +188,14 @@ def testAll(self):
 
     g = FacetNormal(cell)
     _test_object(g, (dim,), ())
-    #g = CellNormal(cell)
+    # g = CellNormal(cell)
     #_test_object(g, (dim,), ())
 
     g = CellVolume(cell)
     _test_object(g, (), ())
     g = Circumradius(cell)
     _test_object(g, (), ())
-    #g = CellSurfaceArea(cell)
+    # g = CellSurfaceArea(cell)
     #_test_object(g, (), ())
 
     g = FacetArea(cell)
@@ -199,7 +204,7 @@ def testAll(self):
     _test_object(g, (), ())
     g = MaxFacetEdgeLength(cell)
     _test_object(g, (), ())
-    #g = FacetDiameter(cell)
+    # g = FacetDiameter(cell)
     #_test_object(g, (), ())
 
     a = variable(v0)
@@ -219,11 +224,11 @@ def testAll(self):
     a = variable(f3)
     _test_object(a, (dim*dim+dim+1,), ())
 
-    #a = MultiIndex()
+    # a = MultiIndex()
 
     # --- Non-terminals:
 
-    #a = Indexed()
+    # a = Indexed()
     a = v2[i, j]
     _test_object(a, (), (i, j))
     a = v2[0, k]
@@ -262,42 +267,42 @@ def testAll(self):
     a = cross(v13D, f13D)
     _test_object(a, (3,), ())
 
-    #a = Sum()
+    # a = Sum()
     a = v0 + f0 + v0
     _test_object(a, (), ())
     a = v1 + f1 + v1
     _test_object(a, (dim,), ())
     a = v2 + f2 + v2
     _test_object(a, (dim, dim), ())
-    #a = Product()
+    # a = Product()
     a = 3*v0*(2.0*v0)*f0*(v0*3.0)
     _test_object(a, (), ())
-    #a = Division()
+    # a = Division()
     a = v0 / 2.0
     _test_object(a, (), ())
     a = v0 / f0
     _test_object(a, (), ())
     a = v0 / (f0 + 7)
     _test_object(a, (), ())
-    #a = Power()
+    # a = Power()
     a = f0**3
     _test_object(a, (), ())
     a = (f0*2)**1.23
     _test_object(a, (), ())
 
-    #a = ListTensor()
+    # a = ListTensor()
     a = as_vector([1.0, 2.0*f0, f0**2])
     _test_object(a, (3,), ())
     a = as_matrix([[1.0, 2.0*f0, f0**2],
-                [1.0, 2.0*f0, f0**2]])
+                   [1.0, 2.0*f0, f0**2]])
     _test_object(a, (2, 3), ())
-    a = as_tensor([ [[0.00, 0.01, 0.02],
-                     [0.10, 0.11, 0.12] ],
-                  [ [1.00, 1.01, 1.02],
-                    [1.10, 1.11, 1.12]] ])
+    a = as_tensor([[[0.00, 0.01, 0.02],
+                    [0.10, 0.11, 0.12]],
+                   [[1.00, 1.01, 1.02],
+                    [1.10, 1.11, 1.12]]])
     _test_object(a, (2, 2, 3), ())
 
-    #a = ComponentTensor()
+    # a = ComponentTensor()
     a = as_vector(v1[i]*f1[j], i)
     _test_object(a, (dim,), (j,))
     a = as_matrix(v1[i]*f1[j], (j, i))
@@ -437,7 +442,7 @@ def testAll(self):
 
     # TODO:
 
-    #a = SpatialDerivative()
+    # a = SpatialDerivative()
     a = f0.dx(0)
     _test_object(a, (), ())
     a = f0.dx(i)
@@ -518,14 +523,14 @@ def testAll(self):
     a = rot(f1)
     _test_object(a, (), ())
 
-    #a = PositiveRestricted(v0)
+    # a = PositiveRestricted(v0)
     #_test_object(a, (), ())
     a = v0('+')
     _test_object(a, (), ())
     a = v0('+')*f0
     _test_object(a, (), ())
 
-    #a = NegativeRestricted(v0)
+    # a = NegativeRestricted(v0)
     #_test_object(a, (), ())
     a = v0('-')
     _test_object(a, (), ())
@@ -588,11 +593,11 @@ def testAll(self):
     # --- Form transformations:
 
     a = f0*v0*dx + f0*v0*dot(f1, v1)*dx
-    #b = lhs(a) # TODO
-    #c = rhs(a) # TODO
+    # b = lhs(a) # TODO
+    # c = rhs(a) # TODO
     d = derivative(a, f1, v1)
     f = action(d)
-    #e = action(b)
+    # e = action(b)
 
     # --- Check which classes have been created
     ic, dc = Expr.ufl_disable_profiling()
diff --git a/test/test_degree_estimation.py b/test/test_degree_estimation.py
index 214e42b..3c344a8 100755
--- a/test/test_degree_estimation.py
+++ b/test/test_degree_estimation.py
@@ -16,8 +16,8 @@ def test_total_degree_estimation():
     V2 = FiniteElement("CG", triangle, 2)
     VV = VectorElement("CG", triangle, 3)
     VM = V1 * V2
-    O1 = OuterProductElement(V1, V1)
-    O2 = OuterProductElement(V2, V1)
+    O1 = TensorProductElement(V1, V1)
+    O2 = TensorProductElement(V2, V1)
     v1 = Argument(V1, 2)
     v2 = Argument(V2, 3)
     f1, f2 = Coefficients(VM)
diff --git a/test/test_derivative.py b/test/test_derivative.py
index dcdeff7..45e7a40 100755
--- a/test/test_derivative.py
+++ b/test/test_derivative.py
@@ -1,6 +1,8 @@
 #!/usr/bin/env py.test
 # -*- coding: utf-8 -*-
 
+from __future__ import print_function
+
 __authors__ = "Martin Sandve Alnæs"
 __date__ = "2009-02-17 -- 2009-02-17"
 
@@ -20,9 +22,10 @@ def assertEqualBySampling(actual, expected):
     b = bd.preprocessed_form.integrals_by_type("cell")[0].integrand()
 
     assert ([ad.function_replace_map[ac] for ac in ad.reduced_coefficients]
-           == [bd.function_replace_map[bc] for bc in bd.reduced_coefficients])
+            == [bd.function_replace_map[bc] for bc in bd.reduced_coefficients])
 
     n = ad.num_coefficients
+
     def make_value(c):
         if isinstance(c, Coefficient):
             z = 0.3
@@ -77,7 +80,7 @@ def _test(self, f, df):
     wv = 11.0
 
     x = xv
-    mapping = { v: vv, u: uv, w: wv }
+    mapping = {v: vv, u: uv, w: wv}
 
     dfv1 = derivative(f(w), w, v)
     dfv2 = df(w, v)
@@ -93,124 +96,168 @@ def _test(self, f, df):
 
 # --- Literals
 
+
 def testScalarLiteral(self):
-    def f(w):     return as_ufl(1)
+    def f(w): return as_ufl(1)
+
     def df(w, v): return zero()
     _test(self, f, df)
 
+
 def testIdentityLiteral(self):
-    def f(w):     return Identity(2)[i, i]
+    def f(w): return Identity(2)[i, i]
+
     def df(w, v): return zero()
     _test(self, f, df)
 
 # --- Form arguments
 
+
 def testCoefficient(self):
-    def f(w):     return w
+    def f(w): return w
+
     def df(w, v): return v
     _test(self, f, df)
 
+
 def testArgument(self):
-    def f(w):     return TestFunction(FiniteElement("CG", triangle, 1))
+    def f(w): return TestFunction(FiniteElement("CG", triangle, 1))
+
     def df(w, v): return zero()
     _test(self, f, df)
 
 # --- Geometry
 
+
 def testSpatialCoordinate(self):
-    def f(w):     return SpatialCoordinate(triangle)[0]
+    def f(w): return SpatialCoordinate(triangle)[0]
+
     def df(w, v): return zero()
     _test(self, f, df)
 
+
 def testFacetNormal(self):
-    def f(w):     return FacetNormal(triangle)[0]
+    def f(w): return FacetNormal(triangle)[0]
+
     def df(w, v): return zero()
     _test(self, f, df)
 
-#def testCellSurfaceArea(self):
+# def testCellSurfaceArea(self):
 #    def f(w):     return CellSurfaceArea(triangle)
 #    def df(w, v): return zero()
 #    _test(self, f, df)
 
+
 def testFacetArea(self):
-    def f(w):     return FacetArea(triangle)
+    def f(w): return FacetArea(triangle)
+
     def df(w, v): return zero()
     _test(self, f, df)
 
+
 def testCircumradius(self):
-    def f(w):     return Circumradius(triangle)
+    def f(w): return Circumradius(triangle)
+
     def df(w, v): return zero()
     _test(self, f, df)
 
+
 def testCellVolume(self):
-    def f(w):     return CellVolume(triangle)
+    def f(w): return CellVolume(triangle)
+
     def df(w, v): return zero()
     _test(self, f, df)
 
 # --- Basic operators
 
+
 def testSum(self):
-    def f(w):     return w + 1
+    def f(w): return w + 1
+
     def df(w, v): return v
     _test(self, f, df)
 
+
 def testProduct(self):
-    def f(w):     return 3*w
+    def f(w): return 3*w
+
     def df(w, v): return 3*v
     _test(self, f, df)
 
+
 def testPower(self):
-    def f(w):     return w**3
+    def f(w): return w**3
+
     def df(w, v): return 3*w**2*v
     _test(self, f, df)
 
+
 def testDivision(self):
-    def f(w):     return w / 3.0
+    def f(w): return w / 3.0
+
     def df(w, v): return v / 3.0
     _test(self, f, df)
 
+
 def testDivision2(self):
-    def f(w):     return 3.0 / w
+    def f(w): return 3.0 / w
+
     def df(w, v): return -3.0 * v / w**2
     _test(self, f, df)
 
+
 def testExp(self):
-    def f(w):     return exp(w)
+    def f(w): return exp(w)
+
     def df(w, v): return v*exp(w)
     _test(self, f, df)
 
+
 def testLn(self):
-    def f(w):     return ln(w)
+    def f(w): return ln(w)
+
     def df(w, v): return v / w
     _test(self, f, df)
 
+
 def testCos(self):
-    def f(w):     return cos(w)
+    def f(w): return cos(w)
+
     def df(w, v): return -v*sin(w)
     _test(self, f, df)
 
+
 def testSin(self):
-    def f(w):     return sin(w)
+    def f(w): return sin(w)
+
     def df(w, v): return v*cos(w)
     _test(self, f, df)
 
+
 def testTan(self):
-    def f(w):     return tan(w)
+    def f(w): return tan(w)
+
     def df(w, v): return v*2.0/(cos(2.0*w) + 1.0)
     _test(self, f, df)
 
+
 def testAcos(self):
-    def f(w):     return acos(w/1000)
+    def f(w): return acos(w/1000)
+
     def df(w, v): return -(v/1000)/sqrt(1.0 - (w/1000)**2)
     _test(self, f, df)
 
+
 def testAsin(self):
-    def f(w):     return asin(w/1000)
+    def f(w): return asin(w/1000)
+
     def df(w, v): return (v/1000)/sqrt(1.0 - (w/1000)**2)
     _test(self, f, df)
 
+
 def testAtan(self):
-    def f(w):     return atan(w)
+    def f(w): return atan(w)
+
     def df(w, v): return v/(1.0 + w**2)
     _test(self, f, df)
 
@@ -218,31 +265,42 @@ def testAtan(self):
 
 # --- Abs and conditionals
 
+
 def testAbs(self):
-    def f(w):     return abs(w)
+    def f(w): return abs(w)
+
     def df(w, v): return sign(w)*v
     _test(self, f, df)
 
+
 def testConditional(self):
     def cond(w): return lt(1.0, 2.0)
-    def f(w):     return conditional(cond(w), 2*w, 3*w)
+
+    def f(w): return conditional(cond(w), 2*w, 3*w)
+
     def df(w, v): return 2*v
     _test(self, f, df)
 
     def cond(w): return lt(2.0, 1.0)
-    def f(w):     return conditional(cond(w), 2*w, 3*w)
+
+    def f(w): return conditional(cond(w), 2*w, 3*w)
+
     def df(w, v): return 3*v
     _test(self, f, df)
 
-def testConditional(self): # This will fail without bugfix in derivative
+
+def testConditional(self):  # This will fail without bugfix in derivative
     def cond(w): return lt(w, 1.0)
-    def f(w):     return conditional(cond(w), 2*w, 3*w)
+
+    def f(w): return conditional(cond(w), 2*w, 3*w)
+
     def df(w, v): return (conditional(cond(w), 1, 0) * 2*v +
                           conditional(cond(w), 0, 1) * 3*v)
     _test(self, f, df)
 
 # --- Tensor algebra basics
 
+
 def testIndexSum(self):
     def f(w):
         # 3*w + 4*w**2 + 5*w**3
@@ -250,22 +308,24 @@ def testIndexSum(self):
         b = as_vector((3, 4, 5))
         i, = indices(1)
         return a[i]*b[i]
+
     def df(w, v): return 3*v + 4*2*w*v + 5*3*w**2*v
     _test(self, f, df)
 
+
 def testListTensor(self):
     v = variable(as_ufl(42))
     f = as_tensor((
-            ( (0,      0), (0,   0) ),
-            ( (v,    2*v), (0,   0) ),
-            ( (v**2,   1), (2, v/2) ),
-            ))
+        ((0, 0), (0, 0)),
+            ((v, 2*v), (0, 0)),
+            ((v**2, 1), (2, v/2)),
+    ))
     assert f.ufl_shape == (3, 2, 2)
     g = as_tensor((
-            ( (0, 0), (0, 0) ),
-            ( (1, 2), (0, 0) ),
-            ( (84, 0), (0, 0.5) ),
-            ))
+        ((0, 0), (0, 0)),
+            ((1, 2), (0, 0)),
+            ((84, 0), (0, 0.5)),
+    ))
     assert g.ufl_shape == (3, 2, 2)
     dfv = diff(f, v)
     x = None
@@ -276,6 +336,7 @@ def testListTensor(self):
 
 # --- Coefficient and argument input configurations
 
+
 def test_single_scalar_coefficient_derivative(self):
     cell = triangle
     V = FiniteElement("CG", cell, 1)
@@ -285,6 +346,7 @@ def test_single_scalar_coefficient_derivative(self):
     b = derivative(a, u, v)
     self.assertEqualAfterPreprocessing(b, 3*(u*(2*v)))
 
+
 def test_single_vector_coefficient_derivative(self):
     cell = triangle
     V = VectorElement("CG", cell, 1)
@@ -295,6 +357,7 @@ def test_single_vector_coefficient_derivative(self):
     expected = 3*(2*(u[i]*v[i]))
     assertEqualBySampling(actual, expected)
 
+
 def test_multiple_coefficient_derivative(self):
     cell = triangle
     V = FiniteElement("CG", cell, 1)
@@ -315,6 +378,7 @@ def test_multiple_coefficient_derivative(self):
     expected = cos(uv)*vv * (uw[i]*uw[i]) + (uw[j]*vw[j])*2 * sin(uv)
     assertEqualBySampling(actual, expected)
 
+
 def test_indexed_coefficient_derivative(self):
     cell = triangle
     I = Identity(cell.geometric_dimension())
@@ -324,7 +388,7 @@ def test_indexed_coefficient_derivative(self):
     v = TestFunction(V)
 
     w = dot(u, nabla_grad(u))
-    #a = dot(w, w)
+    # a = dot(w, w)
     a = (u[i]*u[k].dx(i)) * w[k]
 
     actual = derivative(a, u[0], v)
@@ -334,6 +398,7 @@ def test_indexed_coefficient_derivative(self):
 
     assertEqualBySampling(actual, expected)
 
+
 def test_multiple_indexed_coefficient_derivative(self):
     cell = tetrahedron
     I = Identity(cell.geometric_dimension())
@@ -350,6 +415,7 @@ def test_multiple_indexed_coefficient_derivative(self):
 
     assertEqualBySampling(actual, expected)
 
+
 def test_segregated_derivative_of_convection(self):
     cell = tetrahedron
     V = FiniteElement("CG", cell, 1)
@@ -375,7 +441,7 @@ def test_segregated_derivative_of_convection(self):
             fd = compute_form_data(form)
             pf = fd.preprocessed_form
             a = expand_indices(pf)
-            #print (i,j), str(a)
+            # print (i,j), str(a)
 
     k = Index()
     for i in range(cell.geometric_dimension()):
@@ -386,6 +452,7 @@ def test_segregated_derivative_of_convection(self):
 
 # --- User provided derivatives of coefficients
 
+
 def test_coefficient_derivatives(self):
     V = FiniteElement("Lagrange", triangle, 1)
 
@@ -396,7 +463,7 @@ def test_coefficient_derivatives(self):
     df = Coefficient(V, count=2)
     dg = Coefficient(V, count=3)
     u = Coefficient(V, count=4)
-    cd = { f: df, g: dg }
+    cd = {f: df, g: dg}
 
     integrand = inner(f, g)
     expected = (df*dv)*g + f*(dg*dv)
@@ -408,6 +475,7 @@ def test_coefficient_derivatives(self):
     assert (actual*dx).signature() == (expected*dx).signature()
     self.assertEqual(replace(actual, fd.function_replace_map), expected)
 
+
 def test_vector_coefficient_derivatives(self):
     V = VectorElement("Lagrange", triangle, 1)
     VV = TensorElement("Lagrange", triangle, 1)
@@ -418,7 +486,7 @@ def test_vector_coefficient_derivatives(self):
     g = Coefficient(V, count=1)
     f = Coefficient(V, count=2)
     u = Coefficient(V, count=3)
-    cd = { f: df }
+    cd = {f: df}
 
     integrand = inner(f, g)
 
@@ -430,7 +498,8 @@ def test_vector_coefficient_derivatives(self):
     fd = compute_form_data(J)
     actual = fd.preprocessed_form.integrals()[0].integrand()
     assert (actual*dx).signature() == (expected*dx).signature()
-    #self.assertEqual(replace(actual, fd.function_replace_map), expected)
+    # self.assertEqual(replace(actual, fd.function_replace_map), expected)
+
 
 def test_vector_coefficient_derivatives_of_product(self):
     V = VectorElement("Lagrange", triangle, 1)
@@ -443,35 +512,19 @@ def test_vector_coefficient_derivatives_of_product(self):
     dg = Coefficient(VV, count=2)
     f = Coefficient(V, count=3)
     u = Coefficient(V, count=4)
-    cd = { f: df, g: dg }
+    cd = {f: df, g: dg}
 
     integrand = f[i]*g[i]
 
     i0, i1, i2, i3, i4 = [Index(count=c) for c in range(5)]
     expected = as_tensor(df[i2, i1]*dv[i1], (i2,))[i0]*g[i0] +\
-               f[i0]*as_tensor(dg[i4, i3]*dv[i3], (i4,))[i0]
+        f[i0]*as_tensor(dg[i4, i3]*dv[i3], (i4,))[i0]
 
     F = integrand*dx
     J = derivative(F, u, dv, cd)
     fd = compute_form_data(J)
     actual = fd.preprocessed_form.integrals()[0].integrand()
 
-    # Keeping this snippet here for a while for debugging purposes
-    if 0:
-        print(('\n', 'str:'))
-        print((str(actual)))
-        print((str(expected)))
-        print(('\n', 'repr:'))
-        print((repr(actual)))
-        print((repr(expected)))
-        from ufl.algorithms import tree_format
-        open('actual.txt', 'w').write(tree_format(actual))
-        open('expected.txt', 'w').write(tree_format(expected))
-        print(('\n', 'equal:'))
-        print((str(actual) == str(expected)))
-        print((repr(actual) == repr(expected)))
-        print((actual == expected))
-
     # Tricky case! These are equal in representation except
     # that the outermost sum/indexsum are swapped.
     # Sampling the expressions instead of comparing representations.
@@ -483,6 +536,7 @@ def test_vector_coefficient_derivatives_of_product(self):
 
 # --- Some actual forms
 
+
 def testHyperElasticity(self):
     cell = interval
     element = FiniteElement("CG", cell, 2)
@@ -517,7 +571,7 @@ def testHyperElasticity(self):
     F_expression = strip_variables(F.integrals_by_type("cell")[0].integrand())
     J_expression = strip_variables(J.integrals_by_type("cell")[0].integrand())
 
-    #classes = set(c.__class__ for c in post_traversal(f_expression))
+    # classes = set(c.__class__ for c in post_traversal(f_expression))
 
     Kv = .2
     bv = .3
@@ -545,22 +599,23 @@ def testHyperElasticity(self):
         return dw
 
     w, b, K = form_data_f.original_form.coefficients()
-    mapping = { K: Kv, b: bv, w: Nw }
+    mapping = {K: Kv, b: bv, w: Nw}
     fv2 = f_expression((0,), mapping)
     self.assertAlmostEqual(fv, fv2)
 
     w, b, K = form_data_F.original_form.coefficients()
     v, = form_data_F.original_form.arguments()
-    mapping = { K: Kv, b: bv, v: Nv, w: Nw }
+    mapping = {K: Kv, b: bv, v: Nv, w: Nw}
     Fv2 = F_expression((0,), mapping)
     self.assertAlmostEqual(Fv, Fv2)
 
     w, b, K = form_data_J.original_form.coefficients()
     v, u = form_data_J.original_form.arguments()
-    mapping = { K: Kv, b: bv, v: Nv, u: Nu, w: Nw }
+    mapping = {K: Kv, b: bv, v: Nv, u: Nu, w: Nw}
     Jv2 = J_expression((0,), mapping)
     self.assertAlmostEqual(Jv, Jv2)
 
+
 def test_mass_derived_from_functional(self):
     cell = triangle
     V = FiniteElement("CG", cell, 1)
@@ -572,13 +627,14 @@ def test_mass_derived_from_functional(self):
     f = (w**2/2)*dx
     L = w*v*dx
     a = u*v*dx
-    F  = derivative(f, w, v)
+    F = derivative(f, w, v)
     J1 = derivative(L, w, u)
     J2 = derivative(F, w, u)
     # TODO: assert something
 
 # --- Interaction with replace
 
+
 def test_derivative_replace_works_together(self):
     cell = triangle
     V = FiniteElement("CG", cell, 1)
@@ -591,7 +647,7 @@ def test_derivative_replace_works_together(self):
     M = cos(f)*sin(g)
     F = derivative(M, f, v)
     J = derivative(F, f, u)
-    JR = replace(J, { f: g })
+    JR = replace(J, {f: g})
 
     F2 = -sin(f)*v*sin(g)
     J2 = -cos(f)*u*v*sin(g)
@@ -603,6 +659,7 @@ def test_derivative_replace_works_together(self):
 
 # --- Scratch space
 
+
 def test_foobar(self):
     element = VectorElement("Lagrange", triangle, 1)
     v = TestFunction(element)
@@ -613,7 +670,7 @@ def test_foobar(self):
 
     def planarGrad(u):
         return as_matrix([[u[0].dx(0), 0, u[0].dx(1)],
-                          [ 0, 0, 0 ],
+                          [0, 0, 0],
                           [u[1].dx(0), 0, u[1].dx(1)]])
 
     def epsilon(u):
diff --git a/test/test_diff.py b/test/test_diff.py
index ec0b444..98109cb 100755
--- a/test/test_diff.py
+++ b/test/test_diff.py
@@ -149,6 +149,7 @@ def testTan(v):
 #    def df(v): return -1/sqrt(1.0 - v**2)
 #    _test(f, df)
 
+
 def testAtan(v):
     def f(v):
         return atan(v)
@@ -173,7 +174,8 @@ def testIndexSum(v):
 
 def testCoefficient():
     v = Constant(triangle)
-    assert round(expand_derivatives(diff(v,v))-1.0, 7) == 0
+    assert round(expand_derivatives(diff(v, v))-1.0, 7) == 0
+
 
 def testDiffX():
     cell = triangle
diff --git a/test/test_domains.py b/test/test_domains.py
index 6e23708..fe18042 100755
--- a/test/test_domains.py
+++ b/test/test_domains.py
@@ -60,9 +60,9 @@ def test_domains_sort_by_name():
     domains2 = [Mesh(cell, ufl_id=hash(cell.cellname()))
                 for cell in sorted(all_cells)]
     sdomains = sorted(domains1, key=lambda D: (D.geometric_dimension(),
-                                          D.topological_dimension(),
-                                          D.ufl_cell(),
-                                          D.ufl_id()))
+                                               D.topological_dimension(),
+                                               D.ufl_cell(),
+                                               D.ufl_id()))
     assert sdomains != domains1
     assert sdomains == domains2
 
@@ -100,7 +100,7 @@ def test_simple_domain_case():
     assert M.ufl_domains() == (D, )
 
 
-def test_creating_domains_with_coordinate_fields(): # FIXME: Rewrite for new approach
+def test_creating_domains_with_coordinate_fields():  # FIXME: Rewrite for new approach
     # Definition of higher order domain, element, coefficient, form
 
     # Mesh with P2 representation of coordinates
diff --git a/test/test_elements.py b/test/test_elements.py
index a2e66d0..98f2424 100755
--- a/test/test_elements.py
+++ b/test/test_elements.py
@@ -19,6 +19,10 @@ def test_scalar_galerkin():
                 element = FiniteElement(family, cell, p)
                 assert element.value_shape() == ()
                 assert element == eval(repr(element))
+    for p in range(1, 10):
+        for family in ("TDG", "Discontinuous Taylor"):
+            element = FiniteElement(family, interval, p)
+            assert element.value_shape() == ()
 
 
 def test_vector_galerkin():
diff --git a/test/test_expand_indices.py b/test/test_expand_indices.py
index bbc91f0..f0ae687 100755
--- a/test/test_expand_indices.py
+++ b/test/test_expand_indices.py
@@ -17,9 +17,11 @@ from ufl.algorithms.renumbering import renumber_indices
 from ufl.classes import Sum, Product
 
 # TODO: Test expand_indices2 throuroughly for correctness, then efficiency:
-#expand_indices, expand_indices2 = expand_indices2, expand_indices
+# expand_indices, expand_indices2 = expand_indices2, expand_indices
+
 
 class Fixture:
+
     def __init__(self):
         cell = triangle
         element = FiniteElement("Lagrange", cell, 1)
@@ -102,31 +104,37 @@ class Fixture:
             return ((11, 13), (17, 19))
 
         self.x = (1.23, 3.14)
-        self.mapping = { self.sf: SF, self.sf2: SF2, self.vf: VF, self.tf: TF }
+        self.mapping = {self.sf: SF, self.sf2: SF2, self.vf: VF, self.tf: TF}
 
     def compare(self, f, value):
         debug = 0
-        if debug: print(('f', f))
+        if debug:
+            print(('f', f))
         g = expand_derivatives(f)
-        if debug: print(('g', g))
+        if debug:
+            print(('g', g))
         gv = g(self.x, self.mapping)
         assert abs(gv - value) < 1e-7
 
         g = expand_indices(g)
-        if debug: print(('g', g))
+        if debug:
+            print(('g', g))
         gv = g(self.x, self.mapping)
         assert abs(gv - value) < 1e-7
 
         g = renumber_indices(g)
-        if debug: print(('g', g))
+        if debug:
+            print(('g', g))
         gv = g(self.x, self.mapping)
         assert abs(gv - value) < 1e-7
 
+
 @pytest.fixture(scope="module")
 def fixt():
     # Workaround for quick pytest transition
     return Fixture()
 
+
 def test_basic_expand_indices(self, fixt):
     sf = fixt.sf
     vf = fixt.vf
@@ -181,6 +189,7 @@ def test_basic_expand_indices(self, fixt):
     compare(exp(tf[1, 1]), math.exp(19))
     compare(ln(tf[1, 1]), math.log(19))
 
+
 def test_expand_indices_index_sum(self, fixt):
     sf = fixt.sf
     vf = fixt.vf
@@ -193,7 +202,8 @@ def test_expand_indices_index_sum(self, fixt):
     compare(vf[j]*tf.T[j, i]*vf[i], 5*5*11 + 5*7*13 + 5*7*17 + 7*7*19)
     compare(tf[i, i], 11 + 19)
     compare(tf[i, j]*(tf[j, i]+outer(vf, vf)[i, j]), (5*5+11)*11 + (7*5+17)*13 + (7*5+13)*17 + (7*7+19)*19)
-    compare( as_tensor( as_tensor(tf[i, j], (i, j))[k, l], (l, k) )[i, i], 11 + 19 )
+    compare(as_tensor(as_tensor(tf[i, j], (i, j))[k, l], (l, k))[i, i], 11 + 19)
+
 
 def test_expand_indices_derivatives(self, fixt):
     sf = fixt.sf
@@ -207,6 +217,7 @@ def test_expand_indices_derivatives(self, fixt):
     compare(sf.dx(i)*vf[i], 0.30*5 + 0.31*7)
     compare(vf[j].dx(i)*vf[i].dx(j), 0.50*0.50 + 0.51*0.70 + 0.70*0.51 + 0.71*0.71)
 
+
 def test_expand_indices_hyperelasticity(self, fixt):
     sf = fixt.sf
     vf = fixt.vf
@@ -245,8 +256,8 @@ def test_expand_indices_hyperelasticity(self, fixt):
 
     E = (C-I)/2
     E00 = (C00-1)/2
-    E01 = (C01  )/2
-    E10 = (C10  )/2
+    E01 = (C01)/2
+    E10 = (C10)/2
     E11 = (C11-1)/2
     compare(E[0, 0], E00)
     compare(E[0, 1], E01)
@@ -262,6 +273,7 @@ def test_expand_indices_hyperelasticity(self, fixt):
     psi = (K/2)*exp(Q)
     compare(psi, 0.25*math.exp(Qvalue))
 
+
 def test_expand_indices_div_grad(self, fixt):
     sf = fixt.sf
     sf2 = fixt.sf2
@@ -292,6 +304,7 @@ def test_expand_indices_div_grad(self, fixt):
     a = div(grad(tf))
     compare(inner(a, a), (10.00+11.00)**2 + (10.01+11.01)**2 + (10.10+11.10)**2 + (10.11+11.11)**2)
 
+
 def test_expand_indices_nabla_div_grad(self, fixt):
     sf = fixt.sf
     sf2 = fixt.sf2
@@ -311,11 +324,12 @@ def test_expand_indices_nabla_div_grad(self, fixt):
     a = nabla_div(nabla_grad(tf))
     compare(inner(a, a), (10.00+11.00)**2 + (10.01+11.01)**2 + (10.10+11.10)**2 + (10.11+11.11)**2)
 
+
 def xtest_expand_indices_list_tensor_problem(self, fixt):
     print()
     print(('='*40))
     # TODO: This is the case marked in the expand_indices2 implementation
-    #as not working. Fix and then try expand_indices2 on other tests!
+    # as not working. Fix and then try expand_indices2 on other tests!
     V = VectorElement("CG", triangle, 1)
     w = Coefficient(V)
     v = as_vector([w[0], 0])
diff --git a/test/test_form.py b/test/test_form.py
index 9815b7d..c6a0ff4 100755
--- a/test/test_form.py
+++ b/test/test_form.py
@@ -108,7 +108,7 @@ def test_form_empty(mass):
     assert Form([]).empty()
 
 
-def form_integrals(mass, boundary_load):
+def test_form_integrals(mass, boundary_load):
     assert isinstance(mass.integrals(), tuple)
     assert len(mass.integrals()) == 1
     assert mass.integrals()[0].integral_type() == "cell"
@@ -117,3 +117,20 @@ def form_integrals(mass, boundary_load):
     assert isinstance(boundary_load.integrals_by_type("cell"), tuple)
     assert len(boundary_load.integrals_by_type("cell")) == 0
     assert len(boundary_load.integrals_by_type("exterior_facet")) == 1
+
+
+def test_form_call():
+    V = FiniteElement("CG", triangle, 1)
+    v = TestFunction(V)
+    u = TrialFunction(V)
+    f = Coefficient(V)
+    g = Coefficient(V)
+    a = g*inner(grad(u), grad(v))*dx
+    M = a(f, f, coefficients={ g: 1 })
+    assert M == grad(f)**2*dx
+
+    import sys
+    if sys.version_info.major >= 3 and sys.version_info.minor >= 5:
+        a = u*v*dx
+        M = eval("(a @ f) @ g")
+        assert M == g*f*dx
diff --git a/test/test_future_division.py b/test/test_future_division.py
index 2519da1..7b20abd 100755
--- a/test/test_future_division.py
+++ b/test/test_future_division.py
@@ -10,17 +10,20 @@ import pytest
 from ufl import *
 from ufl.classes import Division, FloatValue, IntValue
 
+
 def test_future_true_float_division(self):
     d = as_ufl(20.0) / 10.0
     self.assertIsInstance(d, FloatValue)
     assert float(d) == 2
 
+
 def test_future_true_int_division(self):
     # UFL treats all divisions as true division
     d = as_ufl(40) / 7
     self.assertIsInstance(d, FloatValue)
     assert float(d) == 40.0 / 7.0
-    #self.assertAlmostEqual(float(d), 40 / 7.0, 15)
+    # self.assertAlmostEqual(float(d), 40 / 7.0, 15)
+
 
 def test_future_floor_division_fails(self):
     f = as_ufl(2.0)
diff --git a/test/test_grad.py b/test/test_grad.py
index 7080d67..a8d5eeb 100755
--- a/test/test_grad.py
+++ b/test/test_grad.py
@@ -10,18 +10,21 @@ import pytest
 # This imports everything external code will see from ufl
 from ufl import *
 
-#from ufl.classes import ...
+# from ufl.classes import ...
 from ufl.algorithms import compute_form_data
 
 
 def xtest_grad_div_curl_properties_in_1D(self):
-   _test_grad_div_curl_properties(self, interval)
+    _test_grad_div_curl_properties(self, interval)
+
 
 def xtest_grad_div_curl_properties_in_2D(self):
-   _test_grad_div_curl_properties(self, triangle)
+    _test_grad_div_curl_properties(self, triangle)
+
 
 def xtest_grad_div_curl_properties_in_3D(self):
-   _test_grad_div_curl_properties(self, tetrahedron)
+    _test_grad_div_curl_properties(self, tetrahedron)
+
 
 def _test_grad_div_curl_properties(self, cell):
     d = cell.geometric_dimension()
@@ -40,16 +43,18 @@ def _test_grad_div_curl_properties(self, cell):
 
     def eval_s(x, derivatives=()):
         return sum(derivatives)
+
     def eval_v(x, derivatives=()):
         return tuple(float(k)+sum(derivatives) for k in range(d))
+
     def eval_t(x, derivatives=()):
         return tuple(tuple(float(i*j)+sum(derivatives)
                            for i in range(d))
-                           for j in range(d))
+                     for j in range(d))
 
-    mapping = { cs: eval_s, s: eval_s,
-                cv: eval_v, v: eval_v,
-                ct: eval_t, t: eval_t, }
+    mapping = {cs: eval_s, s: eval_s,
+               cv: eval_v, v: eval_v,
+               ct: eval_t, t: eval_t, }
     x = tuple(1.0+float(k) for k in range(d))
 
     assert s.ufl_shape == ()
@@ -133,4 +138,4 @@ def _test_grad_div_curl_properties(self, cell):
     fd8 = compute_form_data(a8)
     fd9 = compute_form_data(a9)
 
-    #self.assertTrue(False) # Just to show it runs
+    # self.assertTrue(False) # Just to show it runs
diff --git a/test/test_indexing.py b/test/test_indexing.py
index 1faa019..a53cdab 100755
--- a/test/test_indexing.py
+++ b/test/test_indexing.py
@@ -28,23 +28,23 @@ def test_annotated_literals():
     assert z.ufl_shape == ()
     assert z.ufl_free_indices == ()
     assert z.ufl_index_dimensions == ()
-    assert z.free_indices() == () # Deprecated interface
-    assert z.index_dimensions() == {} # Deprecated interface
+    #assert z.free_indices() == ()  # Deprecated interface
+    #assert z.index_dimensions() == {}  # Deprecated interface
 
     z = Zero((3,))
     assert z.ufl_shape == (3,)
     assert z.ufl_free_indices == ()
     assert z.ufl_index_dimensions == ()
-    assert z.free_indices() == () # Deprecated interface
-    assert z.index_dimensions() == {} # Deprecated interface
+    #assert z.free_indices() == ()  # Deprecated interface
+    #assert z.index_dimensions() == {}  # Deprecated interface
 
     i = Index(count=2)
     j = Index(count=4)
     # z = Zero((), (2, 4), (3, 5))
     z = Zero((), (j, i), {i: 3, j: 5})
     assert z.ufl_shape == ()
-    assert z.free_indices() == (i, j) # Deprecated interface
-    assert z.index_dimensions() == {i: 3, j: 5} # Deprecated interface
+    #assert z.free_indices() == (i, j)  # Deprecated interface
+    #assert z.index_dimensions() == {i: 3, j: 5}  # Deprecated interface
     assert z.ufl_free_indices == (2, 4)
     assert z.ufl_index_dimensions == (3, 5)
 
diff --git a/test/test_indices.py b/test/test_indices.py
index 6ffba1d..806fd2d 100755
--- a/test/test_indices.py
+++ b/test/test_indices.py
@@ -4,12 +4,13 @@
 import pytest
 
 from ufl import *
-#from ufl.indexutils import *
+# from ufl.indexutils import *
 from ufl.algorithms import *
 from ufl.classes import IndexSum
 
 # TODO: add more expressions to test as many possible combinations of index notation as feasible...
 
+
 def xtest_index_utils(self):
     ii = indices(3)
     assert ii == unique_indices(ii)
@@ -26,6 +27,7 @@ def xtest_index_utils(self):
     assert ii == single_indices(ii)
     assert () == single_indices(ii+ii)
 
+
 def test_vector_indices(self):
     element = VectorElement("CG", "triangle", 1)
     u = Argument(element, 2)
@@ -33,6 +35,7 @@ def test_vector_indices(self):
     a = u[i]*f[i]*dx
     b = u[j]*f[j]*dx
 
+
 def test_tensor_indices(self):
     element = TensorElement("CG", "triangle", 1)
     u = Argument(element, 2)
@@ -43,6 +46,7 @@ def test_tensor_indices(self):
     with pytest.raises(UFLException):
         d = (u[i, i]+f[j, i])*dx
 
+
 def test_indexed_sum1(self):
     element = VectorElement("CG", "triangle", 1)
     u = Argument(element, 2)
@@ -51,6 +55,7 @@ def test_indexed_sum1(self):
     with pytest.raises(UFLException):
         a*dx
 
+
 def test_indexed_sum2(self):
     element = VectorElement("CG", "triangle", 1)
     v = Argument(element, 2)
@@ -60,6 +65,7 @@ def test_indexed_sum2(self):
     with pytest.raises(UFLException):
         a*dx
 
+
 def test_indexed_sum3(self):
     element = VectorElement("CG", "triangle", 1)
     u = Argument(element, 2)
@@ -67,6 +73,7 @@ def test_indexed_sum3(self):
     with pytest.raises(UFLException):
         a = u[i]+f[j]
 
+
 def test_indexed_function1(self):
     element = VectorElement("CG", "triangle", 1)
     v = Argument(element, 2)
@@ -75,6 +82,7 @@ def test_indexed_function1(self):
     aarg = (u[i]+f[i])*v[i]
     a = exp(aarg)*dx
 
+
 def test_indexed_function2(self):
     element = VectorElement("CG", "triangle", 1)
     v = Argument(element, 2)
@@ -89,6 +97,7 @@ def test_indexed_function2(self):
     assert right.ufl_free_indices[0] == i.count()
     b = left * right * dx
 
+
 def test_indexed_function3(self):
     element = VectorElement("CG", "triangle", 1)
     v = Argument(element, 2)
@@ -97,6 +106,7 @@ def test_indexed_function3(self):
     with pytest.raises(UFLException):
         c = sin(u[i] + f[i])*dx
 
+
 def test_vector_from_indices(self):
     element = VectorElement("CG", "triangle", 1)
     v  = TestFunction(element)
@@ -112,6 +122,7 @@ def test_vector_from_indices(self):
     assert len(w.ufl_shape) == 1
     assert len(ww.ufl_shape) == 1
 
+
 def test_matrix_from_indices(self):
     element = VectorElement("CG", "triangle", 1)
     v  = TestFunction(element)
@@ -127,6 +138,7 @@ def test_matrix_from_indices(self):
     assert len(C.ufl_shape) == 2
     assert len(D.ufl_shape) == 2
 
+
 def test_vector_from_list(self):
     element = VectorElement("CG", "triangle", 1)
     v  = TestFunction(element)
@@ -138,15 +150,16 @@ def test_vector_from_list(self):
     assert len(vv.ufl_shape) == 1
     assert len(ww.ufl_shape) == 1
 
+
 def test_matrix_from_list(self):
     element = VectorElement("CG", "triangle", 1)
     v  = TestFunction(element)
     u  = TrialFunction(element)
 
     # create matrix from list
-    A  = as_matrix( [ [u[0], u[1]], [v[0], v[1]] ] )
+    A  = as_matrix([[u[0], u[1]], [v[0], v[1]]])
     # create matrix from indices
-    B  = as_matrix( (v[k]*v[k]) * u[i]*v[j], (j, i) )
+    B  = as_matrix((v[k]*v[k]) * u[i]*v[j], (j, i))
     # Test addition
     C  = A + A
     C  = B + B
@@ -156,6 +169,7 @@ def test_matrix_from_list(self):
     assert len(C.ufl_shape) == 2
     assert len(D.ufl_shape) == 2
 
+
 def test_tensor(self):
     element = VectorElement("CG", "triangle", 1)
     v  = TestFunction(element)
@@ -191,10 +205,11 @@ def test_tensor(self):
 
     # illegal
     with pytest.raises(UFLException):
-        A = as_matrix( [ [u[0], u[1]], [v[0],] ] )
+        A = as_matrix([[u[0], u[1]], [v[0],]])
 
     # ...
 
+
 def test_indexed(self):
     element = VectorElement("CG", "triangle", 1)
     v  = TestFunction(element)
@@ -212,6 +227,7 @@ def test_indexed(self):
     self.assertSameIndices(a, ())
     self.assertIsInstance(a, IndexSum)
 
+
 def test_spatial_derivative(self):
     cell = triangle
     element = VectorElement("CG", cell, 1)
@@ -236,7 +252,7 @@ def test_spatial_derivative(self):
     assert a.ufl_shape == ()
 
     a = v.dx(i, j)
-    #self.assertSameIndices(a, (i,j))
+    # self.assertSameIndices(a, (i,j))
     assert set(a.ufl_free_indices) == {j.count(), i.count()}
     self.assertNotIsInstance(a, IndexSum)
     assert a.ufl_shape == (d,)
@@ -256,5 +272,6 @@ def test_spatial_derivative(self):
     self.assertIsInstance(a, IndexSum)
     assert a.ufl_shape == ()
 
+
 def test_renumbering(self):
     pass
diff --git a/test/test_literals.py b/test/test_literals.py
index 10a9e80..34fdeeb 100755
--- a/test/test_literals.py
+++ b/test/test_literals.py
@@ -10,6 +10,7 @@ from ufl import *
 from ufl.classes import Indexed
 from ufl.constantvalue import Zero, FloatValue, IntValue, as_ufl
 
+
 def test_zero(self):
     z1 = Zero(())
     z2 = Zero(())
@@ -18,11 +19,11 @@ def test_zero(self):
     z5 = FloatValue(0)
     z6 = FloatValue(0.0)
 
-    #self.assertTrue(z1 is z2)
-    #self.assertTrue(z1 is z3)
-    #self.assertTrue(z1 is z4)
-    #self.assertTrue(z1 is z5)
-    #self.assertTrue(z1 is z6)
+    # self.assertTrue(z1 is z2)
+    # self.assertTrue(z1 is z3)
+    # self.assertTrue(z1 is z4)
+    # self.assertTrue(z1 is z5)
+    # self.assertTrue(z1 is z6)
     assert z1 == z1
     assert int(z1) == 0
     assert float(z1) == 0.0
@@ -33,6 +34,7 @@ def test_zero(self):
     self.assertNotEqual(hash(z1), hash(0.0))
     self.assertNotEqual(hash(z1), hash(0))
 
+
 def test_float(self):
     f1 = as_ufl(1)
     f2 = as_ufl(1.0)
@@ -42,12 +44,13 @@ def test_float(self):
     f6 = 3 * FloatValue(2) / 6
 
     assert f1 == f1
-    self.assertNotEqual(f1, f2) # IntValue vs FloatValue, == compares representations!
+    self.assertNotEqual(f1, f2)  # IntValue vs FloatValue, == compares representations!
     assert f2 == f3
     assert f2 == f4
     assert f2 == f5
     assert f2 == f6
 
+
 def test_int(self):
     f1 = as_ufl(1)
     f2 = as_ufl(1.0)
@@ -57,11 +60,12 @@ def test_int(self):
     f6 = 3 * IntValue(2) / 6
 
     assert f1 == f1
-    self.assertNotEqual(f1, f2) # IntValue vs FloatValue, == compares representations!
+    self.assertNotEqual(f1, f2)  # IntValue vs FloatValue, == compares representations!
     assert f1 == f3
     assert f1 == f4
     assert f1 == f5
-    assert f2 == f6 # Division produces a FloatValue
+    assert f2 == f6  # Division produces a FloatValue
+
 
 def test_scalar_sums(self):
     n = 10
@@ -93,8 +97,10 @@ def test_scalar_sums(self):
     assert 2*s[5] == 10
     assert s[6]/3 == 2
 
+
 def test_identity(self):
-    pass # FIXME
+    pass  # FIXME
+
 
 def test_permutation_symbol_3(self):
     e = PermutationSymbol(3)
@@ -110,8 +116,9 @@ def test_permutation_symbol_3(self):
     x = (0, 0, 0)
     self.assertEqual((e[i, j, k] * e[i, j, k])(x), 6)
 
+
 def test_permutation_symbol_n(self):
-    for n in range(2, 5): # tested with upper limit 7, but evaluation is a bit slow then
+    for n in range(2, 5):  # tested with upper limit 7, but evaluation is a bit slow then
         e = PermutationSymbol(n)
         assert e.ufl_shape == (n,)*n
         assert eval(repr(e)) == e
@@ -121,6 +128,7 @@ def test_permutation_symbol_n(self):
         nfac = product(m for m in range(1, n+1))
         assert (e[ii] * e[ii])(x) == nfac
 
+
 def test_unit_dyads(self):
     from ufl.tensors import unit_vectors, unit_matrices
     ei, ej = unit_vectors(2)
diff --git a/test/test_measures.py b/test/test_measures.py
index a4c02c1..ff5c443 100755
--- a/test/test_measures.py
+++ b/test/test_measures.py
@@ -20,18 +20,18 @@ from mockobjects import MockMesh, MockMeshFunction
 def test_construct_forms_from_default_measures():
     # Create defaults:
     dx = Measure("dx")
-    #dE = Measure("dE")
+    # dE = Measure("dE")
 
     ds = Measure("ds")
     dS = Measure("dS")
 
     dP = Measure("dP")
-    #dV = Measure("dV")
+    # dV = Measure("dV")
 
     dc = Measure("dc")
-    #dC = Measure("dC")
-    #dO = Measure("dO")
-    #dI = Measure("dI")
+    # dC = Measure("dC")
+    # dO = Measure("dO")
+    # dI = Measure("dI")
 
     ds_b = Measure("ds_b")
     ds_t = Measure("ds_t")
@@ -41,15 +41,15 @@ def test_construct_forms_from_default_measures():
 
     # Check that names are mapped properly
     assert dx.integral_type() == "cell"
-    #assert dE.integral_type() == "macro_cell"
+    # assert dE.integral_type() == "macro_cell"
 
     assert ds.integral_type() == "exterior_facet"
     assert dS.integral_type() == "interior_facet"
 
     assert dP.integral_type() == "vertex"
     # TODO: Change dP to dV:
-    #assert dP.integral_type() == "point"
-    #assert dV.integral_type() == "vertex"
+    # assert dP.integral_type() == "point"
+    # assert dV.integral_type() == "vertex"
 
     assert dc.integral_type() == "custom"
     assert dC.integral_type() == "cutcell"
diff --git a/test/test_mock_expr.py b/test/test_mock_expr.py
deleted file mode 100755
index 41c6d1a..0000000
--- a/test/test_mock_expr.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env py.test
-# -*- coding: utf-8 -*-
-
-import pytest
-
-from ufl import *
-from ufl.core.expr import Expr
-
-class MockExpr(Expr):
-    "A mock type for unit testing."
-    def __init__(self, shape=None, free_indices=None, index_dimensions=None, cell=None):
-        Expr.__init__(self)
-        self.fields = []
-
-        if not shape is None:
-            self._shape = shape
-            self.fields.append("shape")
-
-        if not free_indices is None:
-            self._free_indices = free_indices
-            self.fields.append("free_indices")
-
-        if not index_dimensions is None:
-            self._index_dimensions = index_dimensions
-            self.fields.append("index_dimensions")
-
-        if not cell is None:
-            self._cell = cell
-            self.fields.append("cell")
-
-    def shape(self):
-        assert hasattr(self, "_shape")
-        return self._shape
-
-    def free_indices(self):
-        assert hasattr(self, "_free_indices")
-        return self._free_indices
-
-    def index_dimensions(self):
-        assert hasattr(self, "_index_dimensions")
-        return self._index_dimensions
-
-    def cell(self):
-        assert hasattr(self, "_cell")
-        return self._cell
-
-    def matches(self, other):
-        for field in self.fields:
-            a = getattr(self, field)()
-            b = getattr(other, field)()
-            if not a == b:
-                return False
-        return True
-
-    def __repr__(self):
-        return "MockExpr(%s)" % ", ".join("%s=%s" % (k, repr(getattr(self, "_%s" % k))) for k in self.fields)
-
-    def __iter__(self):
-        raise NotImplementedError
-
-def test_mock_expr():
-    a = MockExpr(shape=(1,))
-    b = MockExpr(shape=(2,))
-    assert not a.matches(b)
-
-    i, j = indices(2)
-    c = MockExpr(shape=(1, 2), free_indices=(i, j), index_dimensions={i:2, j:3}, cell=triangle)
-    d = MockExpr(shape=(1, 2), free_indices=(i, j), index_dimensions={i:2, j:3}, cell=triangle)
-    assert c.matches(d)
-
-    e = FiniteElement("CG", triangle, 1)
-    f = Coefficient(e)
-    g = MockExpr(shape=(), free_indices=(), index_dimensions={}, cell=triangle)
-    assert g.matches(f)
-    h = MockExpr(shape=(1,), free_indices=(), index_dimensions={}, cell=triangle)
-    assert not h.matches(f)
diff --git a/test/test_new_ad.py b/test/test_new_ad.py
index 4862f19..99022fd 100755
--- a/test/test_new_ad.py
+++ b/test/test_new_ad.py
@@ -9,7 +9,7 @@ from ufl.classes import Grad
 from ufl.algorithms import tree_format
 from ufl.algorithms.renumbering import renumber_indices
 from ufl.algorithms.apply_derivatives import apply_derivatives, GenericDerivativeRuleset, \
-     GradRuleset, VariableRuleset, GateauxDerivativeRuleset
+    GradRuleset, VariableRuleset, GateauxDerivativeRuleset
 
 
 # Note: the old tests in test_automatic_differentiation.py are a bit messy
@@ -75,7 +75,7 @@ def test_literal_derivatives_are_zero():
 
     # Generic ruleset handles literals directly:
     for l in literals:
-        for sh in [(), (d,), (d,d+1)]:
+        for sh in [(), (d,), (d, d+1)]:
             assert GenericDerivativeRuleset(sh)(l) == zero(l.ufl_shape + sh)
 
     # Variables
@@ -163,7 +163,7 @@ def test_grad_ruleset():
     # Literals
     assert rules(one) == zero((d,))
     assert rules(two) == zero((d,))
-    assert rules(I) == zero((d,d,d))
+    assert rules(I) == zero((d, d, d))
 
     # Assumed piecewise constant geometry
     for g in [n, volume]:
@@ -178,29 +178,29 @@ def test_grad_ruleset():
 
     # Piecewise constant coefficients (Constant)
     assert rules(r) == zero((d,))
-    assert rules(vr) == zero((d,d))
-    assert rules(grad(r)) == zero((d,d))
-    assert rules(grad(vr)) == zero((d,d,d))
+    assert rules(vr) == zero((d, d))
+    assert rules(grad(r)) == zero((d, d))
+    assert rules(grad(vr)) == zero((d, d, d))
 
     # Piecewise constant coefficients (DG0)
     assert rules(f0) == zero((d,))
-    assert rules(vf0) == zero((d,d))
-    assert rules(grad(f0)) == zero((d,d))
-    assert rules(grad(vf0)) == zero((d,d,d))
+    assert rules(vf0) == zero((d, d))
+    assert rules(grad(f0)) == zero((d, d))
+    assert rules(grad(vf0)) == zero((d, d, d))
 
     # Piecewise linear coefficients
     assert rules(f1) == grad(f1)
     assert rules(vf1) == grad(vf1)
-    #assert rules(grad(f1)) == zero((d,d)) # TODO: Use degree to make this work
-    #assert rules(grad(vf1)) == zero((d,d,d))
+    # assert rules(grad(f1)) == zero((d,d)) # TODO: Use degree to make this work
+    # assert rules(grad(vf1)) == zero((d,d,d))
 
     # Piecewise quadratic coefficients
     assert rules(grad(f2)) == grad(grad(f2))
     assert rules(grad(vf2)) == grad(grad(vf2))
 
     # Indexed coefficients
-    assert renumber_indices(apply_derivatives(grad(vf2[0]))) == renumber_indices(grad(vf2)[0,:])
-    assert renumber_indices(apply_derivatives(grad(vf2[1])[0])) == renumber_indices(grad(vf2)[1,0])
+    assert renumber_indices(apply_derivatives(grad(vf2[0]))) == renumber_indices(grad(vf2)[0, :])
+    assert renumber_indices(apply_derivatives(grad(vf2[1])[0])) == renumber_indices(grad(vf2)[1, 0])
 
     # Grad of gradually more complex expressions
     assert apply_derivatives(grad(2*f0)) == zero((d,))
diff --git a/test/test_piecewise_checks.py b/test/test_piecewise_checks.py
index 892b633..76fe2e2 100755
--- a/test/test_piecewise_checks.py
+++ b/test/test_piecewise_checks.py
@@ -13,7 +13,7 @@ from ufl.checks import is_cellwise_constant
 
 def get_domains():
     all_cells = [
-        #vertex,
+        # vertex,
         interval,
         triangle,
         quadrilateral,
diff --git a/test/test_reference_shapes.py b/test/test_reference_shapes.py
index 22d3a21..b581356 100755
--- a/test/test_reference_shapes.py
+++ b/test/test_reference_shapes.py
@@ -5,8 +5,9 @@ import pytest
 
 from ufl import *
 
+
 def test_reference_shapes():
-    #show_elements()
+    # show_elements()
 
     cell = Cell("triangle", 3)
 
@@ -28,7 +29,7 @@ def test_reference_shapes():
 
     T = TensorElement("CG", cell, 1)
     assert T.value_shape() == (3, 3)
-    assert T.reference_value_shape() == (3,3)
+    assert T.reference_value_shape() == (3, 3)
 
     S = TensorElement("CG", cell, 1, symmetry=True)
     assert S.value_shape() == (3, 3)
diff --git a/test/test_scratch.py b/test/test_scratch.py
index fcbed29..15a71eb 100755
--- a/test/test_scratch.py
+++ b/test/test_scratch.py
@@ -13,17 +13,20 @@ from six.moves import zip
 # This imports everything external code will see from ufl
 from ufl import *
 from ufl.log import error, warning
-from ufl.assertions import ufl_assert
 from ufl.tensors import as_scalar, unit_indexed_tensor, unwrap_list_tensor
 
 # TODO: Import only what you need from classes and algorithms:
 from ufl.classes import Grad, FormArgument, Zero, Indexed, FixedIndex, ListTensor
 
+
 class MockForwardAD:
+
     def __init__(self):
         self._w = ()
         self._v = ()
+
         class Obj:
+
             def __init__(self):
                 self._data = {}
         self._cd = Obj()
@@ -41,7 +44,7 @@ class MockForwardAD:
             o, = o.ufl_operands
             ngrads += 1
         if not isinstance(o, FormArgument):
-            error("Expecting gradient of a FormArgument, not %r" % (o,))
+            error("Expecting gradient of a FormArgument, not %s" % repr(o))
 
         def apply_grads(f):
             if not isinstance(f, FormArgument):
@@ -76,8 +79,8 @@ class MockForwardAD:
                 vcomp = tuple(vcomp)
             else:
                 error("Expecting argument or component of argument.")
-            ufl_assert(all(isinstance(k, FixedIndex) for k in vcomp),
-                       "Expecting only fixed indices in variation.")
+            if not all(isinstance(k, FixedIndex) for k in vcomp):
+                error("Expecting only fixed indices in variation.")
             return vval, vcomp
 
         def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
@@ -98,7 +101,8 @@ class MockForwardAD:
 
             # Analyse differentiation variable coefficient
             if isinstance(w, FormArgument):
-                if not w == o: continue
+                if not w == o:
+                    continue
                 wshape = w.ufl_shape
 
                 if isinstance(v, FormArgument):
@@ -113,21 +117,23 @@ class MockForwardAD:
                             gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
 
                 else:
-                    ufl_assert(wshape == (), "Expecting scalar coefficient in this branch.")
+                    if wshape != ():
+                        error("Expecting scalar coefficient in this branch.")
                     # Case: d/dt [w + t v[...]]
                     wval, wcomp = w, ()
 
                     vval, vcomp = analyse_variation_argument(v)
                     gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
 
-            elif isinstance(w, Indexed): # This path is tested in unit tests, but not actually used?
+            elif isinstance(w, Indexed):  # This path is tested in unit tests, but not actually used?
                 # Case: d/dt [w[...] + t v[...]]
                 # Case: d/dt [w[...] + t v]
                 wval, wcomp = w.ufl_operands
-                if not wval == o: continue
+                if not wval == o:
+                    continue
                 assert isinstance(wval, FormArgument)
-                ufl_assert(all(isinstance(k, FixedIndex) for k in wcomp),
-                           "Expecting only fixed indices in differentiation variable.")
+                if not all(isinstance(k, FixedIndex) for k in wcomp):
+                    error("Expecting only fixed indices in differentiation variable.")
                 wshape = wval.ufl_shape
 
                 vval, vcomp = analyse_variation_argument(v)
@@ -149,8 +155,9 @@ class MockForwardAD:
                 # Make sure we have a tuple to match the self._v tuple
                 if not isinstance(oprimes, tuple):
                     oprimes = (oprimes,)
-                    ufl_assert(len(oprimes) == len(self._v), "Got a tuple of arguments, "+\
-                                   "expecting a matching tuple of coefficient derivatives.")
+                    if len(oprimes) != len(self._v):
+                        error("Got a tuple of arguments, "
+                              "expecting a matching tuple of coefficient derivatives.")
 
                 # Compute dg/dw_j = dg/dw_h : v.
                 # Since we may actually have a tuple of oprimes and vs in a
@@ -177,10 +184,11 @@ def test_unit_tensor(self):
     E22_10, ii = unit_indexed_tensor((2, 2), (1, 0))
     # TODO: Evaluate and assert values
 
+
 def test_unwrap_list_tensor(self):
     lt = as_tensor((1, 2))
     expected = [((0,), 1),
-                ((1,), 2),]
+                ((1,), 2), ]
     comp = unwrap_list_tensor(lt)
     assert comp == expected
 
@@ -188,7 +196,7 @@ def test_unwrap_list_tensor(self):
     expected = [((0, 0), 1),
                 ((0, 1), 2),
                 ((1, 0), 3),
-                ((1, 1), 4),]
+                ((1, 1), 4), ]
     comp = unwrap_list_tensor(lt)
     assert comp == expected
 
@@ -201,10 +209,11 @@ def test_unwrap_list_tensor(self):
                 ((1, 0, 0), 11),
                 ((1, 0, 1), 12),
                 ((1, 1, 0), 13),
-                ((1, 1, 1), 14),]
+                ((1, 1, 1), 14), ]
     comp = unwrap_list_tensor(lt)
     assert comp == expected
 
+
 def test__forward_coefficient_ad__grad_of_scalar_coefficient(self):
     U = FiniteElement("CG", triangle, 1)
     u = Coefficient(U)
@@ -228,6 +237,7 @@ def test__forward_coefficient_ad__grad_of_scalar_coefficient(self):
     assert g == f
     assert dg == df
 
+
 def test__forward_coefficient_ad__grad_of_vector_coefficient(self):
     V = VectorElement("CG", triangle, 1)
     v = Coefficient(V)
@@ -251,6 +261,7 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient(self):
     assert g == f
     assert dg == df
 
+
 def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_variation(self):
     V = VectorElement("CG", triangle, 1)
     v = Coefficient(V)
@@ -263,9 +274,9 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     mad._w = (v[0],)
     mad._v = (dv[1],)
     f = grad(v)
-    df = grad(as_vector((dv[1], 0))) # Mathematically this would be the natural result
+    df = grad(as_vector((dv[1], 0)))  # Mathematically this would be the natural result
     j, k = indices(2)
-    df = as_tensor(Identity(2)[0, j]*grad(dv)[1, k], (j, k)) # Actual representation should have grad right next to dv
+    df = as_tensor(Identity(2)[0, j]*grad(dv)[1, k], (j, k))  # Actual representation should have grad right next to dv
     g, dg = mad.grad(f)
     if 0:
         print(('\nf    ', f))
@@ -278,7 +289,7 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     assert g == f
     self.assertEqual((inner(dg, dg)*dx).signature(),
                      (inner(df, df)*dx).signature())
-    #assert dg == df # Expected to fail because of different index numbering
+    # assert dg == df # Expected to fail because of different index numbering
 
     # Multiple components of variation:
     # grad(grad(c))[0,1,:,:] -> grad(grad(dc))[1,0,:,:]
@@ -289,9 +300,9 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     df = grad(as_vector((dv[1], dv[0])))
     # Actual representation should have grad right next to dv:
     j0, k0 = indices(2)
-    j1, k1 = indices(2) # Using j0,k0 for both terms gives different signature
+    j1, k1 = indices(2)  # Using j0,k0 for both terms gives different signature
     df = (as_tensor(Identity(2)[0, j0]*grad(dv)[1, k0], (j0, k0))
-        + as_tensor(Identity(2)[1, j1]*grad(dv)[0, k1], (j1, k1)))
+          + as_tensor(Identity(2)[1, j1]*grad(dv)[0, k1], (j1, k1)))
     g, dg = mad.grad(f)
     print(('\nf    ', f))
     print(('df   ', df))
@@ -303,7 +314,8 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     assert g == f
     self.assertEqual((inner(dg, dg)*dx).signature(),
                      (inner(df, df)*dx).signature())
-    #assert dg == df # Expected to fail because of different index numbering
+    # assert dg == df # Expected to fail because of different index numbering
+
 
 def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_variation_in_list(self):
     V = VectorElement("CG", triangle, 1)
@@ -317,9 +329,9 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     mad._w = (v,)
     mad._v = (as_vector((dv[1], 0)),)
     f = grad(v)
-    df = grad(as_vector((dv[1], 0))) # Mathematically this would be the natural result
+    df = grad(as_vector((dv[1], 0)))  # Mathematically this would be the natural result
     j, k = indices(2)
-    df = as_tensor(Identity(2)[0, j]*grad(dv)[1, k], (j, k)) # Actual representation should have grad right next to dv
+    df = as_tensor(Identity(2)[0, j]*grad(dv)[1, k], (j, k))  # Actual representation should have grad right next to dv
     g, dg = mad.grad(f)
     if 0:
         print(('\nf    ', f))
@@ -332,7 +344,7 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     assert g == f
     self.assertEqual((inner(dg, dg)*dx).signature(),
                      (inner(df, df)*dx).signature())
-    #assert dg == df # Expected to fail because of different index numbering
+    # assert dg == df # Expected to fail because of different index numbering
 
     # Multiple components of variation:
     # grad(grad(c))[0,1,:,:] -> grad(grad(dc))[1,0,:,:]
@@ -343,9 +355,9 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     df = grad(as_vector((dv[1], dv[0])))
     # Actual representation should have grad right next to dv:
     j0, k0 = indices(2)
-    j1, k1 = indices(2) # Using j0,k0 for both terms gives different signature
+    j1, k1 = indices(2)  # Using j0,k0 for both terms gives different signature
     df = (as_tensor(Identity(2)[0, j0]*grad(dv)[1, k0], (j0, k0))
-        + as_tensor(Identity(2)[1, j1]*grad(dv)[0, k1], (j1, k1)))
+          + as_tensor(Identity(2)[1, j1]*grad(dv)[0, k1], (j1, k1)))
     g, dg = mad.grad(f)
     print(('\nf    ', f))
     print(('df   ', df))
@@ -357,7 +369,7 @@ def test__forward_coefficient_ad__grad_of_vector_coefficient__with_component_var
     assert g == f
     self.assertEqual((inner(dg, dg)*dx).signature(),
                      (inner(df, df)*dx).signature())
-    #assert dg == df # Expected to fail because of different index numbering
+    # assert dg == df # Expected to fail because of different index numbering
 
 
 def test__forward_coefficient_ad__grad_of_tensor_coefficient(self):
@@ -383,6 +395,7 @@ def test__forward_coefficient_ad__grad_of_tensor_coefficient(self):
     assert g == f
     assert dg == df
 
+
 def test__forward_coefficient_ad__grad_of_tensor_coefficient__with_component_variation(self):
     W = TensorElement("CG", triangle, 1)
     w = Coefficient(W)
@@ -397,11 +410,11 @@ def test__forward_coefficient_ad__grad_of_tensor_coefficient__with_component_var
     mad._w = (w[wc],)
     mad._v = (dw[dwc],)
     f = grad(w)
-    df = grad(as_matrix(((0, 0), (dw[dwc], 0)))) # Mathematically this is it.
+    df = grad(as_matrix(((0, 0), (dw[dwc], 0))))  # Mathematically this is it.
     i, j, k = indices(3)
     E = outer(Identity(2)[wc[0], i], Identity(2)[wc[1], j])
     Ddw = grad(dw)[dwc + (k,)]
-    df = as_tensor(E*Ddw, (i, j, k)) # Actual representation should have grad next to dv
+    df = as_tensor(E*Ddw, (i, j, k))  # Actual representation should have grad next to dv
     g, dg = mad.grad(f)
     if 0:
         print(('\nf    ', f))
@@ -414,4 +427,4 @@ def test__forward_coefficient_ad__grad_of_tensor_coefficient__with_component_var
     assert g == f
     self.assertEqual((inner(dg, dg)*dx).signature(),
                      (inner(df, df)*dx).signature())
-    #assert dg == df # Expected to fail because of different index numbering
+    # assert dg == df # Expected to fail because of different index numbering
diff --git a/test/test_signature.py b/test/test_signature.py
index 6c9138c..2f8c0b0 100755
--- a/test/test_signature.py
+++ b/test/test_signature.py
@@ -23,6 +23,7 @@ from itertools import chain
 # TODO: Test that we do not get collisions for some large sets of generated forms
 # TODO: How do we know that we have tested the signature reliably enough?
 
+
 def domain_numbering(*cells):
     renumbering = {}
     for i, cell in enumerate(cells):
@@ -30,6 +31,7 @@ def domain_numbering(*cells):
         renumbering[domain] = i
     return renumbering
 
+
 def test_domain_signatures_of_cell2domains(self):
     all_cells = (interval, quadrilateral, hexahedron, triangle, tetrahedron)
     for cell in all_cells:
@@ -40,8 +42,9 @@ def test_domain_signatures_of_cell2domains(self):
         # Signature data holds when constructing two domains from a cell:
         D1 = as_domain(cell)
         D2 = as_domain(cell)
-        self.assertEqual(D1._ufl_signature_data_({D1:0}),
-                         D2._ufl_signature_data_({D2:0}))
+        self.assertEqual(D1._ufl_signature_data_({D1: 0}),
+                         D2._ufl_signature_data_({D2: 0}))
+
 
 def compute_unique_terminal_hashdatas(hashdatas):
     count = 0
@@ -57,24 +60,26 @@ def compute_unique_terminal_hashdatas(hashdatas):
         assert isinstance(d, dict)
         # Sorting values by hash should be stable at least in a single test run:
         t = tuple(sorted(list(d.values()), key=lambda x: hash(x)))
-        #print t
+        # print t
 
         # Add the hashdata values tuple to sets based on itself, its hash,
         # and its repr (not sure why I included repr anymore?)
-        hashes.add(hash(t)) # This will fail if t is not hashable, which it should be!
+        hashes.add(hash(t))  # This will fail if t is not hashable, which it should be!
         data.add(t)
         reprs.add(repr(t))
         count += 1
 
     return count, len(data), len(reprs), len(hashes)
 
+
 def test_terminal_hashdata_depends_on_literals(self):
     reprs = set()
     hashes = set()
+
     def forms():
         i, j = indices(2)
         for d in (2, 3):
-            domain = as_domain({2:triangle,3:tetrahedron}[d])
+            domain = as_domain({2: triangle, 3: tetrahedron}[d])
             x = SpatialCoordinate(domain)
             I = Identity(d)
             for fv in (1.1, 2.2):
@@ -93,9 +98,11 @@ def test_terminal_hashdata_depends_on_literals(self):
     assert len(reprs) == c
     assert len(hashes) == c
 
+
 def test_terminal_hashdata_depends_on_geometry(self):
     reprs = set()
     hashes = set()
+
     def forms():
         i, j = indices(2)
         cells = (triangle, tetrahedron)
@@ -106,12 +113,12 @@ def test_terminal_hashdata_depends_on_geometry(self):
             n = FacetNormal(cell)
             r = Circumradius(cell)
             a = FacetArea(cell)
-            #s = CellSurfaceArea(cell)
+            # s = CellSurfaceArea(cell)
             v = CellVolume(cell)
             I = Identity(d)
 
             ws = (x, n)
-            qs = (r, a, v) #, s)
+            qs = (r, a, v)  # , s)
             for w in ws:
                 for q in qs:
                     expr = (I[0, j]*(q*w[j]))
@@ -121,13 +128,14 @@ def test_terminal_hashdata_depends_on_geometry(self):
                     yield compute_terminal_hashdata(expr, domain_numbering(*cells))
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    assert c == 2*3*2 # len(ws)*len(qs)*len(cells)
+    assert c == 2*3*2  # len(ws)*len(qs)*len(cells)
     assert d == c
     assert r == c
     assert h == c
     assert len(reprs) == c
     assert len(hashes) == c
 
+
 def test_terminal_hashdata_depends_on_form_argument_properties(self):
     reprs = set()
     hashes = set()
@@ -150,7 +158,7 @@ def test_terminal_hashdata_depends_on_form_argument_properties(self):
                         W2 = VectorElement(family, cell, degree, dim=d+1)
                         T = TensorElement(family, cell, degree)
                         S = TensorElement(family, cell, degree, symmetry=True)
-                        S2 = TensorElement(family, cell, degree, shape=(d, d), symmetry={(0, 0):(1, 1)})
+                        S2 = TensorElement(family, cell, degree, shape=(d, d), symmetry={(0, 0): (1, 1)})
                         elements = [V, W, W2, T, S, S2]
                         assert len(elements) == nelm
 
@@ -168,17 +176,18 @@ def test_terminal_hashdata_depends_on_form_argument_properties(self):
                                 yield compute_terminal_hashdata(expr, renumbering)
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    c1 = nreps * len(cells) * len(degrees) * len(families) * nelm * 2 # Number of cases with repetitions
+    c1 = nreps * len(cells) * len(degrees) * len(families) * nelm * 2  # Number of cases with repetitions
     assert c == c1
 
-    c0 = len(cells) * len(degrees) * (len(families)-1) * nelm * 2 # Number of unique cases, "CG" == "Lagrange"
-    #c0 = len(cells) * len(degrees) * (len(families)) * nelm * 2 # Number of unique cases, "CG" != "Lagrange"
+    c0 = len(cells) * len(degrees) * (len(families)-1) * nelm * 2  # Number of unique cases, "CG" == "Lagrange"
+    # c0 = len(cells) * len(degrees) * (len(families)) * nelm * 2 # Number of unique cases, "CG" != "Lagrange"
     assert d == c0
     assert r == c0
     assert h == c0
     assert len(reprs) == c0
     assert len(hashes) == c0
 
+
 def test_terminal_hashdata_does_not_depend_on_coefficient_count_values_only_ordering(self):
     reprs = set()
     hashes = set()
@@ -186,6 +195,7 @@ def test_terminal_hashdata_does_not_depend_on_coefficient_count_values_only_orde
     cells = (interval, triangle, hexahedron)
     assert len(counts) == 7
     nreps = 1
+
     def forms():
         for rep in range(nreps):
             for cell in cells:
@@ -204,15 +214,16 @@ def test_terminal_hashdata_does_not_depend_on_coefficient_count_values_only_orde
                     yield compute_terminal_hashdata(expr, renumbering)
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    c0 = len(cells) # Number of actually unique cases from a code generation perspective
-    c1 = len(counts) * c0 # Number of unique cases from a symbolic representation perspective
+    c0 = len(cells)  # Number of actually unique cases from a code generation perspective
+    c1 = len(counts) * c0  # Number of unique cases from a symbolic representation perspective
     assert len(reprs) == c1
     assert len(hashes) == c1
-    assert c == nreps * c1 # number of inner loop executions in forms() above
+    assert c == nreps * c1  # number of inner loop executions in forms() above
     assert d == c0
     assert r == c0
     assert h == c0
 
+
 def test_terminal_hashdata_does_depend_on_argument_number_values(self):
     # TODO: Include part numbers as well
     reprs = set()
@@ -220,6 +231,7 @@ def test_terminal_hashdata_does_depend_on_argument_number_values(self):
     counts = list(range(4))
     cells = (interval, triangle, hexahedron)
     nreps = 2
+
     def forms():
         for rep in range(nreps):
             for cell in cells:
@@ -234,15 +246,16 @@ def test_terminal_hashdata_does_depend_on_argument_number_values(self):
                     yield compute_terminal_hashdata(expr, domain_numbering(*cells))
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    c0 = len(cells) * len(counts) # Number of actually unique cases from a code generation perspective
-    c1 = 1 * c0 # Number of unique cases from a symbolic representation perspective
+    c0 = len(cells) * len(counts)  # Number of actually unique cases from a code generation perspective
+    c1 = 1 * c0  # Number of unique cases from a symbolic representation perspective
     assert len(reprs) == c1
     assert len(hashes) == c1
-    self.assertEqual(c, nreps * c1) # number of inner loop executions in forms() above
+    self.assertEqual(c, nreps * c1)  # number of inner loop executions in forms() above
     assert d == c0
     assert r == c0
     assert h == c0
 
+
 def test_domain_signature_data_does_not_depend_on_domain_label_value(self):
     cells = [triangle, tetrahedron, hexahedron]
     s0s = set()
@@ -252,9 +265,9 @@ def test_domain_signature_data_does_not_depend_on_domain_label_value(self):
         d0 = Mesh(cell)
         d1 = Mesh(cell, ufl_id=1)
         d2 = Mesh(cell, ufl_id=2)
-        s0 = d0._ufl_signature_data_({ d0: 0 })
-        s1 = d1._ufl_signature_data_({ d1: 0 })
-        s2 = d2._ufl_signature_data_({ d2: 0 })
+        s0 = d0._ufl_signature_data_({d0: 0})
+        s1 = d1._ufl_signature_data_({d1: 0})
+        s2 = d2._ufl_signature_data_({d2: 0})
         assert s0 == s1
         assert s0 == s2
         s0s.add(s0)
@@ -264,6 +277,7 @@ def test_domain_signature_data_does_not_depend_on_domain_label_value(self):
     assert len(s1s) == len(cells)
     assert len(s2s) == len(cells)
 
+
 def test_terminal_hashdata_does_not_depend_on_domain_label_value(self):
     reprs = set()
     hashes = set()
@@ -272,6 +286,7 @@ def test_terminal_hashdata_does_not_depend_on_domain_label_value(self):
     domains = [Mesh(cell, ufl_id=ufl_id) for cell in cells for ufl_id in ufl_ids]
     nreps = 2
     num_exprs = 2
+
     def forms():
         for rep in range(nreps):
             for domain in domains:
@@ -281,10 +296,10 @@ def test_terminal_hashdata_does_not_depend_on_domain_label_value(self):
                 x = SpatialCoordinate(domain)
                 n = FacetNormal(domain)
                 exprs = [inner(x, n), inner(f, v)]
-                assert num_exprs == len(exprs) # Assumed in checks below
+                assert num_exprs == len(exprs)  # Assumed in checks below
 
                 # This numbering needs to be recreated to count 'domain' and 'f' as 0 each time:
-                renumbering = { f: 0, domain: 0 }
+                renumbering = {f: 0, domain: 0}
 
                 for expr in exprs:
                     reprs.add(repr(expr))
@@ -292,15 +307,16 @@ def test_terminal_hashdata_does_not_depend_on_domain_label_value(self):
                     yield compute_terminal_hashdata(expr, renumbering)
 
     c, d, r, h = compute_unique_terminal_hashdatas(forms())
-    c0 = num_exprs * len(cells) # Number of actually unique cases from a code generation perspective
-    c1 = num_exprs * len(domains) # Number of unique cases from a symbolic representation perspective
+    c0 = num_exprs * len(cells)  # Number of actually unique cases from a code generation perspective
+    c1 = num_exprs * len(domains)  # Number of unique cases from a symbolic representation perspective
     assert len(reprs) == c1
     assert len(hashes) == c1
-    self.assertEqual(c, nreps * c1) # number of inner loop executions in forms() above
+    self.assertEqual(c, nreps * c1)  # number of inner loop executions in forms() above
     assert d == c0
     assert r == c0
     assert h == c0
 
+
 def compute_unique_multiindex_hashdatas(hashdatas):
     count = 0
     data = set()
@@ -313,9 +329,11 @@ def compute_unique_multiindex_hashdatas(hashdatas):
         count += 1
     return count, len(data), len(reprs), len(hashes)
 
+
 def test_multiindex_hashdata_depends_on_fixed_index_values(self):
     reprs = set()
     hashes = set()
+
     def hashdatas():
         for i in range(3):
             for ii in ((i,), (i, 0), (1, i)):
@@ -327,13 +345,15 @@ def test_multiindex_hashdata_depends_on_fixed_index_values(self):
 
     c, d, r, h = compute_unique_multiindex_hashdatas(hashdatas())
     assert c == 9
-    assert d == 9-1 # (1,0 is repeated, therefore -1)
+    assert d == 9-1  # (1,0 is repeated, therefore -1)
     assert len(reprs) == 9-1
     assert len(hashes) == 9-1
 
+
 def test_multiindex_hashdata_does_not_depend_on_counts(self):
     reprs = set()
     hashes = set()
+
     def hashdatas():
         ijs = []
         iind = indices(3)
@@ -354,10 +374,12 @@ def test_multiindex_hashdata_does_not_depend_on_counts(self):
     assert len(reprs) == 3+9+9
     assert len(hashes) == 3+9+9
 
+
 def test_multiindex_hashdata_depends_on_the_order_indices_are_observed(self):
     reprs = set()
     hashes = set()
     nrep = 3
+
     def hashdatas():
         for rep in range(nrep):
             # Resetting index_numbering for each repetition,
@@ -367,13 +389,13 @@ def test_multiindex_hashdata_depends_on_the_order_indices_are_observed(self):
             index_numbering = {}
             i, j, k, l = indices(4)
             for expr in (MultiIndex((i,)),
-                         MultiIndex((i,)), # r
+                         MultiIndex((i,)),  # r
                          MultiIndex((i, j)),
                          MultiIndex((j, i)),
-                         MultiIndex((i, j)), # r
+                         MultiIndex((i, j)),  # r
                          MultiIndex((i, j, k)),
                          MultiIndex((k, j, i)),
-                         MultiIndex((j, i))): # r
+                         MultiIndex((j, i))):  # r
                 reprs.add(repr(expr))
                 hashes.add(hash(expr))
                 yield compute_multiindex_hashdata(expr, index_numbering)
@@ -404,6 +426,7 @@ def check_unique_signatures(forms):
     assert len(reprs) == count
     assert len(hashes) == count
 
+
 def test_signature_is_affected_by_element_properties(self):
     def forms():
         for family in ("CG", "DG"):
@@ -419,6 +442,7 @@ def test_signature_is_affected_by_element_properties(self):
                     yield a
     check_unique_signatures(forms())
 
+
 def test_signature_is_affected_by_domains(self):
     def forms():
         for cell in (triangle, tetrahedron):
@@ -431,6 +455,7 @@ def test_signature_is_affected_by_domains(self):
                         yield a
     check_unique_signatures(forms())
 
+
 def test_signature_of_forms_with_diff(self):
     def forms():
         for cell in (triangle, tetrahedron):
@@ -448,6 +473,7 @@ def test_signature_of_forms_with_diff(self):
                 yield a
     check_unique_signatures(forms())
 
+
 def test_signature_of_form_depend_on_coefficient_numbering_across_integrals(self):
     cell = triangle
     V = FiniteElement("CG", cell, 1)
@@ -460,6 +486,7 @@ def test_signature_of_form_depend_on_coefficient_numbering_across_integrals(self
     self.assertTrue(M1.signature() != M3.signature())
     self.assertTrue(M2.signature() != M3.signature())
 
+
 def test_signature_of_forms_change_with_operators(self):
     def forms():
         for cell in (triangle, tetrahedron):
@@ -470,8 +497,8 @@ def test_signature_of_forms_change_with_operators(self):
                   (u+v)+(u/v),
                   (u+v)*(u/v),
                   (u*v)*(u*v),
-                  (u+v)*(u*v), # (!) same
-                  #(u*v)*(u+v), # (!) same
+                  (u+v)*(u*v),  # (!) same
+                  # (u*v)*(u+v), # (!) same
                   (u*v)+(u+v),
                   ]
             for f in fs:
diff --git a/test/test_simplify.py b/test/test_simplify.py
index 1863d7b..48dbfff 100755
--- a/test/test_simplify.py
+++ b/test/test_simplify.py
@@ -6,6 +6,7 @@ from ufl.classes import Sum, Product
 import math
 from ufl import *
 
+
 def xtest_zero_times_argument(self):
     # FIXME: Allow zero forms
     element = FiniteElement("CG", triangle, 1)
@@ -18,6 +19,7 @@ def xtest_zero_times_argument(self):
     assert len(compute_form_data(a).arguments) == 2
     assert len(compute_form_data(b).arguments) == 2
 
+
 def test_divisions(self):
     element = FiniteElement("CG", triangle, 1)
     f = Coefficient(element)
@@ -39,9 +41,10 @@ def test_divisions(self):
     assert a == b
 
     # Test simplification of division by self (this simplification has been disabled)
-    #a = f/f
-    #b = 1
-    #assert a == b
+    # a = f/f
+    # b = 1
+    # assert a == b
+
 
 def test_products(self):
     element = FiniteElement("CG", triangle, 1)
@@ -60,7 +63,8 @@ def test_products(self):
     assert f*g == g*f
 
     # Test simplification of self-multiplication (this simplification has been disabled)
-    #assert f*f == f**2
+    # assert f*f == f**2
+
 
 def test_sums(self):
     element = FiniteElement("CG", triangle, 1)
@@ -75,22 +79,23 @@ def test_sums(self):
     assert 0 + f == f
 
     # Test collapsing of basic sum (this simplification has been disabled)
-    #assert f + f == 2 * f
+    # assert f + f == 2 * f
 
     # Test reordering of operands and collapsing sum
-    a = f + g + f # not collapsed, but ordered
-    b = g + f + f # not collapsed, but ordered
-    c = (g + f) + f # not collapsed, but ordered
-    d = f + (f + g) # not collapsed, but ordered
+    a = f + g + f  # not collapsed, but ordered
+    b = g + f + f  # not collapsed, but ordered
+    c = (g + f) + f  # not collapsed, but ordered
+    d = f + (f + g)  # not collapsed, but ordered
     assert a == b
     assert a == c
     assert a == d
 
     # Test reordering of operands and collapsing sum
-    a = f + f + g # collapsed
-    b = g + (f + f) # collapsed
+    a = f + f + g  # collapsed
+    b = g + (f + f)  # collapsed
     assert a == b
 
+
 def test_mathfunctions(self):
     for i in (0.1, 0.3, 0.9):
         assert math.sin(i) == sin(i)
@@ -109,6 +114,7 @@ def test_mathfunctions(self):
         # TODO: Implement automatic simplification of conditionals?
         assert i == float(Min(i, i+1))
 
+
 def test_indexing(self):
     u = VectorConstant(triangle)
     v = VectorConstant(triangle)
diff --git a/test/test_split.py b/test/test_split.py
index 7e9ca7a..380def3 100755
--- a/test/test_split.py
+++ b/test/test_split.py
@@ -10,6 +10,7 @@ import pytest
 
 from ufl import *
 
+
 def test_split(self):
     cell = triangle
     d = cell.geometric_dimension()
@@ -21,14 +22,15 @@ def test_split(self):
     r = TensorElement("CG", cell, 1, symmetry={(1, 0): (0, 1)}, shape=(d, d))
     m = MixedElement(f, v, w, t, s, r)
 
-    # Shapes of all these functions are correct:
+    # Check that shapes of all these functions are correct:
     assert () == Coefficient(f).ufl_shape
-    self.assertEqual((d,), Coefficient(v).ufl_shape)
-    self.assertEqual((d+1,), Coefficient(w).ufl_shape)
-    self.assertEqual((d, d), Coefficient(t).ufl_shape)
-    self.assertEqual((d, d), Coefficient(s).ufl_shape)
-    self.assertEqual((d, d), Coefficient(r).ufl_shape)
-    self.assertEqual((3*d*d + 2*d + 2,), Coefficient(m).ufl_shape) # sum of value sizes, not accounting for symmetries
+    assert (d,) == Coefficient(v).ufl_shape
+    assert (d+1,) == Coefficient(w).ufl_shape
+    assert (d, d) == Coefficient(t).ufl_shape
+    assert (d, d) == Coefficient(s).ufl_shape
+    assert (d, d) == Coefficient(r).ufl_shape
+    # sum of value sizes, not accounting for symmetries:
+    assert (3*d*d + 2*d + 2,) == Coefficient(m).ufl_shape
 
     # Shapes of subelements are reproduced:
     g = Coefficient(m)
@@ -37,10 +39,28 @@ def test_split(self):
         s -= product(g2.ufl_shape)
     assert s == 0
 
-    # TODO: Should functions on mixed elements (vector+vector) be able to have tensor shape instead of vector shape? Think Marie wants this for BDM+BDM?
+    # Mixed elements of non-scalar subelements are flattened
     v2 = MixedElement(v, v)
     m2 = MixedElement(t, t)
-    #assert d == 2
-    #self.assertEqual((2,2), Coefficient(v2).ufl_shape)
-    self.assertEqual((d+d,), Coefficient(v2).ufl_shape)
-    self.assertEqual((2*d*d,), Coefficient(m2).ufl_shape)
+    # assert d == 2
+    # assert (2,2) == Coefficient(v2).ufl_shape
+    assert (d+d,) == Coefficient(v2).ufl_shape
+    assert (2*d*d,) == Coefficient(m2).ufl_shape
+
+    # Split twice on nested mixed elements gets
+    # the innermost scalar subcomponents
+    t = TestFunction(f*v)
+    assert split(t) == (t[0], as_vector((t[1], t[2])))
+    assert split(split(t)[1]) == (t[1], t[2])
+    t = TestFunction(f*(f*v))
+    assert split(t) == (t[0], as_vector((t[1], t[2], t[3])))
+    assert split(split(t)[1]) == (t[1], as_vector((t[2], t[3])))
+    t = TestFunction((v*f)*(f*v))
+    assert split(t) == (as_vector((t[0], t[1], t[2])),
+                        as_vector((t[3], t[4], t[5])))
+    assert split(split(t)[0]) == (as_vector((t[0], t[1])), t[2])
+    assert split(split(t)[1]) == (t[3], as_vector((t[4], t[5])))
+    assert split(split(split(t)[0])[0]) == (t[0], t[1])
+    assert split(split(split(t)[0])[1]) == (t[2],)
+    assert split(split(split(t)[1])[0]) == (t[3],)
+    assert split(split(split(t)[1])[1]) == (t[4], t[5])
diff --git a/test/test_str.py b/test/test_str.py
index 54b37f8..f9a7c34 100755
--- a/test/test_str.py
+++ b/test/test_str.py
@@ -1,8 +1,5 @@
-#!/usr/bin/env py.test
 # -*- coding: utf-8 -*-
 
-import pytest
-
 from ufl import *
 from ufl.classes import *
 
@@ -10,14 +7,17 @@ from ufl.classes import *
 def test_str_int_value(self):
     assert str(as_ufl(3)) == "3"
 
+
 def test_str_float_value(self):
     assert str(as_ufl(3.14)) == "3.14"
 
+
 def test_str_zero(self):
     x = SpatialCoordinate(triangle)
     assert str(as_ufl(0)) == "0"
-    assert str(0*x) == "(0<(2,), ()>)" # TODO: Not very nice...
-    assert str(0*x*x[Index(42)]) == "(0<(2,), (42,)>)" # TODO: Not very nice...
+    assert str(0*x) == "0 (shape (2,))"
+    assert str(0*x*x[Index(42)]) == "0 (shape (2,), index labels (42,))"
+
 
 def test_str_index(self):
     assert str(Index(3)) == "i_3"
@@ -28,19 +28,24 @@ def test_str_coordinate(self):
     assert str(SpatialCoordinate(triangle)) == "x"
     assert str(SpatialCoordinate(triangle)[0]) == "x[0]"
 
+
 def test_str_normal(self):
     assert str(FacetNormal(triangle)) == "n"
     assert str(FacetNormal(triangle)[0]) == "n[0]"
 
+
 def test_str_circumradius(self):
     assert str(Circumradius(triangle)) == "circumradius"
 
-#def test_str_cellsurfacearea(self):
-#    assert str(CellSurfaceArea(triangle)) == "surfacearea"
+
+# def test_str_cellsurfacearea(self):
+#     assert str(CellSurfaceArea(triangle)) == "surfacearea"
+
 
 def test_str_facetarea(self):
     assert str(FacetArea(triangle)) == "facetarea"
 
+
 def test_str_volume(self):
     assert str(CellVolume(triangle)) == "volume"
 
@@ -51,24 +56,27 @@ def test_str_scalar_argument(self):
     assert str(v) == "v_0"
     assert str(u) == "v_1"
 
-#def test_str_vector_argument(self): # FIXME
 
-#def test_str_scalar_coefficient(self): # FIXME
+# def test_str_vector_argument(self): # FIXME
 
-#def test_str_vector_coefficient(self): # FIXME
+# def test_str_scalar_coefficient(self): # FIXME
 
+# def test_str_vector_coefficient(self): # FIXME
 
-def test_str_list_vector(self):
+
+def test_str_list_vector():
     x, y, z = SpatialCoordinate(tetrahedron)
     v = as_vector((x, y, z))
     assert str(v) == ("[%s, %s, %s]" % (x, y, z))
 
-def test_str_list_vector_with_zero(self):
+
+def test_str_list_vector_with_zero():
     x, y, z = SpatialCoordinate(tetrahedron)
     v = as_vector((x, 0, 0))
     assert str(v) == ("[%s, 0, 0]" % (x,))
 
-def test_str_list_matrix(self):
+
+def test_str_list_matrix():
     x, y = SpatialCoordinate(triangle)
     v = as_matrix(((2*x, 3*y),
                    (4*x, 5*y)))
@@ -78,7 +86,8 @@ def test_str_list_matrix(self):
     d = str(5*y)
     assert str(v) == ("[\n  [%s, %s],\n  [%s, %s]\n]" % (a, b, c, d))
 
-def test_str_list_matrix_with_zero(self):
+
+def test_str_list_matrix_with_zero():
     x, y = SpatialCoordinate(triangle)
     v = as_matrix(((2*x, 3*y),
                    (0, 0)))
@@ -87,5 +96,6 @@ def test_str_list_matrix_with_zero(self):
     c = str(as_vector((0, 0)))
     assert str(v) == ("[\n  [%s, %s],\n%s\n]" % (a, b, c))
 
+
 # FIXME: Add more tests for tensors collapsing
 #        partly or completely into Zero!
diff --git a/test/test_tensoralgebra.py b/test/test_tensoralgebra.py
index 471cdb4..a25a059 100755
--- a/test/test_tensoralgebra.py
+++ b/test/test_tensoralgebra.py
@@ -1,25 +1,27 @@
-#!/usr/bin/env py.test
 # -*- coding: utf-8 -*-
 """
 Test tensor algebra operators.
 """
 
 import pytest
-
 from ufl import *
 
+
 @pytest.fixture(scope="module")
 def A():
     return as_matrix([[2, 3], [4, 5]])
 
+
 @pytest.fixture(scope="module")
 def B():
     return as_matrix([[6, 7], [8, 9]])
 
+
 @pytest.fixture(scope="module")
 def u():
     return as_vector([10, 20])
 
+
 @pytest.fixture(scope="module")
 def v():
     return as_vector([30, 40])
@@ -35,6 +37,7 @@ def test_repeated_as_tensor(self, A, B, u, v):
     assert u2 == u
     assert v2 == v
 
+
 def test_outer(self, A, B, u, v):
     C = outer(u, v)
     D = as_matrix([[10*30, 10*40], [20*30, 20*40]])
@@ -48,6 +51,7 @@ def test_outer(self, A, B, u, v):
 
     # TODO: Test other ranks
 
+
 def test_inner(self, A, B, u, v):
     C = inner(A, B)
     D = 2*6 + 3*7 + 4*8 + 5*9
@@ -57,6 +61,7 @@ def test_inner(self, A, B, u, v):
     D = 10*30 + 20*40
     self.assertEqualValues(C, D)
 
+
 def test_pow2_inner(self, A, u):
     f = FacetNormal(triangle)[0]
     f2 = f*f
@@ -71,6 +76,7 @@ def test_pow2_inner(self, A, u):
     # Only tensor**2 notation is supported:
     self.assertRaises(UFLException, lambda: A**3)
 
+
 def test_dot(self, A, B, u, v):
     C = dot(u, v)
     D = 10*30 + 20*40
@@ -78,10 +84,11 @@ def test_dot(self, A, B, u, v):
 
     C = dot(A, B)
     dims = (0, 1)
-    D = as_matrix([[sum(A[i, k]*B[k, j] for k in dims) \
-                        for j in dims] for i in dims])
+    D = as_matrix([[sum(A[i, k]*B[k, j] for k in dims)
+                    for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
+
 def test_cross(self):
     u = as_vector([3, 3, 3])
     v = as_vector([2, 2, 2])
@@ -96,29 +103,34 @@ def test_cross(self):
     D = as_vector([0, 0, z])
     self.assertEqualValues(C, D)
 
+
 def xtest_dev(self, A):
     C = dev(A)
-    D = 0*C # FIXME: Add expected value here
+    D = 0*C  # FIXME: Add expected value here
     self.assertEqualValues(C, D)
 
+
 def test_skew(self, A):
     C = skew(A)
     A, dims = A, (0, 1)
     D = 0.5*as_matrix([[A[i, j] - A[j, i] for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
+
 def test_sym(self, A):
     C = sym(A)
     A, dims = A, (0, 1)
     D = 0.5*as_matrix([[A[i, j] + A[j, i] for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
+
 def test_transpose(self, A):
     C = transpose(A)
     dims = (0, 1)
     D = as_matrix([[A[j, i] for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
+
 def test_diag(self, A, u):
     dims = (0, 1)
 
@@ -130,29 +142,34 @@ def test_diag(self, A, u):
     D = as_matrix([[(0 if i != j else u[i]) for j in dims] for i in dims])
     self.assertEqualValues(C, D)
 
+
 def test_diag_vector(self, A):
     dims = (0, 1)
     C = diag_vector(A)
     D = as_vector([A[i, i] for i in dims])
     self.assertEqualValues(C, D)
 
+
 def test_tr(self, A):
     C = tr(A)
     A, dims = A, (0, 1)
     D = sum(A[i, i] for i in dims)
     self.assertEqualValues(C, D)
 
+
 def xtest_det(self, A):
     C = det(A)
-    D = zero() # FIXME: Add expected value here
+    D = zero()  # FIXME: Add expected value here
     self.assertEqualValues(C, D)
 
+
 def xtest_cofac(self, A):
     C = cofac(A)
-    D = 0*C # FIXME: Add expected value here
+    D = 0*C  # FIXME: Add expected value here
     self.assertEqualValues(C, D)
 
+
 def xtest_inv(self, A):
     C = inv(A)
-    D = 0*C # FIXME: Add expected value here
+    D = 0*C  # FIXME: Add expected value here
     self.assertEqualValues(C, D)
diff --git a/test/test_utilities.py b/test/test_utilities.py
index 790af1c..831159d 100755
--- a/test/test_utilities.py
+++ b/test/test_utilities.py
@@ -5,18 +5,20 @@
 Test internal utility functions.
 """
 
-import pytest
 from six.moves import xrange as range
 
-from ufl.utils.indexflattening import shape_to_strides, flatten_multiindex, unflatten_index
+from ufl.utils.indexflattening import (shape_to_strides, flatten_multiindex,
+                                       unflatten_index)
+
 
 def test_shape_to_strides():
-    assert ()         == shape_to_strides(())
-    assert (1,)       == shape_to_strides((3,))
-    assert (2, 1)     == shape_to_strides((3, 2))
-    assert (4, 1)     == shape_to_strides((3, 4))
+    assert () == shape_to_strides(())
+    assert (1,) == shape_to_strides((3,))
+    assert (2, 1) == shape_to_strides((3, 2))
+    assert (4, 1) == shape_to_strides((3, 4))
     assert (12, 4, 1) == shape_to_strides((6, 3, 4))
 
+
 def test_flatten_multiindex_to_multiindex():
     sh = (2, 3, 5)
     strides = shape_to_strides(sh)
@@ -28,8 +30,9 @@ def test_flatten_multiindex_to_multiindex():
                 index2 = unflatten_index(c, strides)
                 assert index == index2
 
+
 def test_indexing_to_component():
-    assert 0 == flatten_multiindex(  (), shape_to_strides(()))
+    assert 0 == flatten_multiindex((), shape_to_strides(()))
     assert 0 == flatten_multiindex((0,), shape_to_strides((2,)))
     assert 1 == flatten_multiindex((1,), shape_to_strides((2,)))
     assert 3 == flatten_multiindex((1, 1), shape_to_strides((2, 2)))
@@ -56,7 +59,9 @@ def test_component_numbering():
 
 
 def test_index_flattening():
-    from ufl.utils.indexflattening import shape_to_strides, flatten_multiindex, unflatten_index
+    from ufl.utils.indexflattening import (shape_to_strides,
+                                           flatten_multiindex,
+                                           unflatten_index)
     # Scalar shape
     s = ()
     st = shape_to_strides(s)
@@ -126,7 +131,7 @@ def test_index_flattening():
     mixed_shape = (6,)
     ts = (2, 2)
     vs = (2,)
-    offset = 4 # product(ts)
+    offset = 4  # product(ts)
 
     # vector element y-component is index offset+1:
     c = (offset + 1,)
@@ -147,7 +152,7 @@ def test_index_flattening():
         i -= 0
         # map back to tensor component:
         c2 = unflatten_index(i, shape_to_strides(ts))
-        assert (k//2, k%2) == c2
+        assert (k//2, k % 2) == c2
 
 
 def test_stackdict():
diff --git a/ufl/__init__.py b/ufl/__init__.py
index 8c53b68..e474abc 100644
--- a/ufl/__init__.py
+++ b/ufl/__init__.py
@@ -1,28 +1,32 @@
 # -*- coding: utf-8 -*-
+# flake8: noqa
 """The Unified Form Language is an embedded domain specific language
 for definition of variational forms intended for finite element
 discretization. More precisely, it defines a fixed interface for choosing
 finite element spaces and defining expressions for weak forms in a
-notation close to mathematical notation.
+notation close to the mathematical one.
 
 This Python module contains the language as well as algorithms to work
 with it.
 
-* To import the language, type::
+* To import the language, type
+::
 
     from ufl import *
 
 * To import the underlying classes an UFL expression tree is built
-  from, type::
+  from, type
+  ::
 
     from ufl.classes import *
 
 * Various algorithms for working with UFL expression trees can be
-  found in::
+  accessed by
+  ::
 
     from ufl.algorithms import *
 
-The classes and algorithms are considered implementation details and
+Classes and algorithms are considered implementation details and
 should not be used in form definitions.
 
 For more details on the language, see
@@ -41,122 +45,179 @@ A very brief overview of the language contents follows:
 
 * Cells::
 
-    AbstractCell, Cell, TensorProductCell, OuterProductCell,
-    vertex, interval, triangle, tetrahedron, quadrilateral, hexahedron
+    - AbstractCell
+    - Cell
+    - TensorProductCell
+    - vertex
+    - interval
+    - triangle
+    - tetrahedron
+    - quadrilateral
+    - hexahedron
 
 * Domains::
 
-    AbstractDomain, Mesh, MeshView, TensorProductMesh
+    - AbstractDomain
+    - Mesh
+    - MeshView
+    - TensorProductMesh
 
 * Sobolev spaces::
 
-    L2, H1, H2, HDiv, HCurl
+    - L2
+    - H1
+    - H2
+    - HDiv
+    - HCurl
 
 * Elements::
 
-    FiniteElement,
-    MixedElement, VectorElement, TensorElement
-    EnrichedElement, RestrictedElement,
-    TensorProductElement, OuterProductElement,
-    HDivElement, HCurlElement
-    BrokenElement, TraceElement
-    FacetElement, InteriorElement
+    - FiniteElement
+    - MixedElement
+    - VectorElement
+    - TensorElement
+    - EnrichedElement
+    - RestrictedElement
+    - TensorProductElement
+    - HDivElement
+    - HCurlElement
+    - BrokenElement
+    - FacetElement
+    - InteriorElement
 
 * Function spaces::
 
-    FunctionSpace
+    - FunctionSpace
 
 * Arguments::
 
-    Argument, TestFunction, TrialFunction,
-    Arguments, TestFunctions, TrialFunctions
+    - Argument
+    - TestFunction
+    - TrialFunction
+    - Arguments
+    - TestFunctions
+    - TrialFunctions
 
 * Coefficients::
 
-    Coefficient, Constant, VectorConstant, TensorConstant
+    - Coefficient
+    - Constant
+    - VectorConstant
+    - TensorConstant
 
 * Splitting form arguments in mixed spaces::
 
-    split
+    - split
 
 * Literal constants::
 
-    Identity, PermutationSymbol
+    - Identity
+    - PermutationSymbol
 
 * Geometric quantities::
 
-    SpatialCoordinate,
-    FacetNormal, CellNormal,
-    CellVolume, Circumradius, MinCellEdgeLength, MaxCellEdgeLength,
-    FacetArea, MinFacetEdgeLength, MaxFacetEdgeLength,
-    Jacobian, JacobianDeterminant, JacobianInverse
+    - SpatialCoordinate
+    - FacetNormal
+    - CellNormal
+    - CellVolume
+    - Circumradius
+    - MinCellEdgeLength
+    - MaxCellEdgeLength
+    - FacetArea
+    - MinFacetEdgeLength
+    - MaxFacetEdgeLength
+    - Jacobian
+    - JacobianDeterminant
+    - JacobianInverse
 
 * Indices::
 
-    Index, indices,
-    i, j, k, l, p, q, r, s
+    - Index
+    - indices
+    - i, j, k, l
+    - p, q, r, s
 
 * Scalar to tensor expression conversion::
 
-    as_tensor, as_vector, as_matrix
+    - as_tensor
+    - as_vector
+    - as_matrix
 
 * Unit vectors and matrices::
 
-    unit_vector, unit_vectors,
-    unit_matrix, unit_matrices
+    - unit_vector
+    - unit_vectors
+    - unit_matrix
+    - unit_matrices
 
 * Tensor algebra operators::
 
-    outer, inner, dot, cross, perp,
-    det, inv, cofac,
-    transpose, tr, diag, diag_vector,
-    dev, skew, sym
+    - outer, inner, dot, cross, perp
+    - det, inv, cofac
+    - transpose, tr, diag, diag_vector
+    - dev, skew, sym
 
 * Elementwise tensor operators::
 
-    elem_mult, elem_div, elem_pow, elem_op
+    - elem_mult
+    - elem_div
+    - elem_pow
+    - elem_op
 
 * Differential operators::
 
-    variable, diff,
-    grad, div, nabla_grad, nabla_div,
-    Dx, Dn, curl, rot
+    - variable
+    - diff,
+    - grad, nabla_grad
+    - div, nabla_div
+    - curl, rot
+    - Dx, Dn
 
 * Nonlinear functions::
 
-    max_value, min_value,
-    abs, sign, sqrt,
-    exp, ln, erf,
-    cos, sin, tan,
-    acos, asin, atan, atan_2,
-    cosh, sinh, tanh,
-    bessel_J, bessel_Y, bessel_I, bessel_K
+    - max_value, min_value
+    - abs, sign
+    - sqrt
+    - exp, ln, erf
+    - cos, sin, tan
+    - acos, asin, atan, atan_2
+    - cosh, sinh, tanh
+    - bessel_J, bessel_Y, bessel_I, bessel_K
+
+* Discontinuous Galerkin operators::
 
-* Discontinuous Galerkin operators:
-    jump, avg, v('+'), v('-'), cell_avg, facet_avg
+    - v('+'), v('-')
+    - jump
+    - avg
+    - cell_avg, facet_avg
 
 * Conditional operators::
 
-    eq, ne, le, ge, lt, gt,
-    <, >, <=, >=,
-    And, Or, Not,
-    conditional
+    - eq, ne, le, ge, lt, gt
+    - <, >, <=, >=
+    - And, Or, Not
+    - conditional
 
 * Integral measures::
 
-    dx, ds, dS, dP,
-    dc, dC, dO, dI, dX
-    ds_b, ds_t, ds_tb, ds_v, dS_h, dS_v
+    - dx, ds, dS, dP
+    - dc, dC, dO, dI, dX
+    - ds_b, ds_t, ds_tb, ds_v, dS_h, dS_v
 
 * Form transformations::
 
-    rhs, lhs, system, functional,
-    replace, replace_integral_domains,
-    adjoint, action, energy_norm,
-    sensitivity_rhs, derivative
+    - rhs, lhs
+    - system
+    - functional
+    - replace, replace_integral_domains
+    - adjoint
+    - action
+    - energy_norm,
+    - sensitivity_rhs
+    - derivative
 """
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -178,8 +239,9 @@ A very brief overview of the language contents follows:
 # Modified by Johannes Ring, 2014.
 # Modified by Andrew T. T. McRae, 2014
 # Modified by Lawrence Mitchell, 2014
+# Modified by Massimiliano Leoni, 2016
 
-__version__ = "2016.1.0"
+__version__ = "2016.2.0"
 
 ########## README
 # Imports here should be what the user sees when doing "from ufl import *",
@@ -198,7 +260,7 @@ from ufl.log import get_handler, get_logger, set_handler, set_level, add_logfile
 
 # Types for geometric quantities
 
-from ufl.cell import as_cell, AbstractCell, Cell, TensorProductCell, OuterProductCell
+from ufl.cell import as_cell, AbstractCell, Cell, TensorProductCell
 from ufl.domain import as_domain, AbstractDomain, Mesh, MeshView, TensorProductMesh
 from ufl.geometry import (
     SpatialCoordinate,
@@ -214,8 +276,8 @@ from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl
 # Finite elements classes
 from ufl.finiteelement import FiniteElementBase, FiniteElement, \
     MixedElement, VectorElement, TensorElement, EnrichedElement, \
-    RestrictedElement, TensorProductElement, OuterProductElement, \
-    HDivElement, HCurlElement, BrokenElement, TraceElement, \
+    RestrictedElement, TensorProductElement, \
+    HDivElement, HCurlElement, BrokenElement, \
     FacetElement, InteriorElement
 
 # Hook to extend predefined element families
@@ -297,11 +359,14 @@ from ufl.objects import (
 # Useful constants
 from math import e, pi
 
-__all__ = [
+
+# Define ufl.* namespace
+from ufl.utils.py23 import as_native_strings
+__all__ = as_native_strings([
     'product',
     'get_handler', 'get_logger', 'set_handler', 'set_level', 'add_logfile',
     'UFLException', 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL',
-    'as_cell', 'AbstractCell', 'Cell', 'TensorProductCell', 'OuterProductCell',
+    'as_cell', 'AbstractCell', 'Cell', 'TensorProductCell',
     'as_domain', 'AbstractDomain', 'Mesh', 'MeshView', 'TensorProductMesh',
     'L2', 'H1', 'H2', 'HCurl', 'HDiv',
     'SpatialCoordinate',
@@ -311,9 +376,9 @@ __all__ = [
     'Jacobian', 'JacobianDeterminant', 'JacobianInverse',
     'FiniteElementBase', 'FiniteElement',
     'MixedElement', 'VectorElement', 'TensorElement', 'EnrichedElement',
-    'RestrictedElement', 'TensorProductElement', 'OuterProductElement',
+    'RestrictedElement', 'TensorProductElement',
     'HDivElement', 'HCurlElement',
-    'BrokenElement', 'TraceElement', 'FacetElement', 'InteriorElement',
+    'BrokenElement', 'FacetElement', 'InteriorElement',
     'register_element', 'show_elements',
     'FunctionSpace',
     'Argument', 'TestFunction', 'TrialFunction',
@@ -351,4 +416,4 @@ __all__ = [
     'quadrilateral', 'hexahedron', 'facet',
     'i', 'j', 'k', 'l', 'p', 'q', 'r', 's',
     'e', 'pi',
-    ]
+    ])
diff --git a/ufl/algebra.py b/ufl/algebra.py
index c4d004f..ff09981 100644
--- a/ufl/algebra.py
+++ b/ufl/algebra.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Basic algebra operations."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,21 +20,19 @@
 #
 # Modified by Anders Logg, 2008
 
-from itertools import chain
-from six import iteritems
-
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
-from ufl.core.expr import Expr
+from ufl.log import error
+from ufl.utils.py23 import as_native_strings
+from ufl.core.ufl_type import ufl_type
+from ufl.core.expr import Expr, ufl_err_str
 from ufl.core.operator import Operator
 from ufl.constantvalue import Zero, zero, ScalarValue, IntValue, as_ufl
 from ufl.checks import is_ufl_scalar, is_true_ufl_scalar
 from ufl.index_combination_utils import merge_unique_indices
 from ufl.sorting import sorted_expr
 from ufl.precedence import parstr
-from ufl.core.ufl_type import ufl_type
 
-#--- Algebraic operators ---
+# --- Algebraic operators ---
+
 
 @ufl_type(num_ops=2,
           inherit_shape_from_operand=0, inherit_indices_from_operand=0,
@@ -72,18 +70,18 @@ class Sum(Operator):
             return as_ufl(a._value + b._value)
         elif sa:
             # Place scalar first
-            #operands = (a, b)
-            pass #a, b = a, b
+            # operands = (a, b)
+            pass  # a, b = a, b
         elif sb:
             # Place scalar first
-            #operands = (b, a)
+            # operands = (b, a)
             a, b = b, a
-        #elif a == b:
+        # elif a == b:
         #    # Replace a+b with 2*foo
         #    return 2*a
         else:
             # Otherwise sort operands in a canonical order
-            #operands = (b, a)
+            # operands = (b, a)
             a, b = sorted_expr((a, b))
 
         # construct and initialize a new Sum object
@@ -98,7 +96,8 @@ class Sum(Operator):
         Operator.__init__(self)
 
     def evaluate(self, x, mapping, component, index_values):
-        return sum(o.evaluate(x, mapping, component, index_values) for o in self.ufl_operands)
+        return sum(o.evaluate(x, mapping, component,
+                              index_values) for o in self.ufl_operands)
 
     def __str__(self):
         ops = [parstr(o, self) for o in self.ufl_operands]
@@ -122,14 +121,15 @@ class Sum(Operator):
         # Implementation with no line splitting:
         return "%s" % " + ".join(ops)
 
-    def __repr__(self):
-        return "Sum(%s)" % ", ".join(repr(o) for o in self.ufl_operands)
 
 @ufl_type(num_ops=2,
           binop="__mul__", rbinop="__rmul__")
 class Product(Operator):
     """The product of two or more UFL objects."""
-    __slots__ = ("ufl_free_indices", "ufl_index_dimensions",)
+    __slots__ = as_native_strings((
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+    ))
 
     def __new__(cls, a, b):
         # Conversion
@@ -139,31 +139,35 @@ class Product(Operator):
         # Type checking
         # Make sure everything is scalar
         if a.ufl_shape or b.ufl_shape:
-            error("Product can only represent products of scalars.")
+            error("Product can only represent products of scalars, "
+                  "got\n\t%s\nand\n\t%s" % (ufl_err_str(a), ufl_err_str(b)))
 
         # Simplification
         if isinstance(a, Zero) or isinstance(b, Zero):
             # Got any zeros? Return zero.
-            fi, fid = merge_unique_indices(a.ufl_free_indices, a.ufl_index_dimensions,
-                                           b.ufl_free_indices, b.ufl_index_dimensions)
+            fi, fid = merge_unique_indices(a.ufl_free_indices,
+                                           a.ufl_index_dimensions,
+                                           b.ufl_free_indices,
+                                           b.ufl_index_dimensions)
             return Zero((), fi, fid)
         sa = isinstance(a, ScalarValue)
         sb = isinstance(b, ScalarValue)
-        if sa and sb: # const * const = const
-            # FIXME: Handle free indices like with zero? I think IntValue may be index annotated now?
+        if sa and sb:  # const * const = const
+            # FIXME: Handle free indices like with zero? I think
+            # IntValue may be index annotated now?
             return as_ufl(a._value * b._value)
-        elif sa: # 1 * b = b
+        elif sa:  # 1 * b = b
             if a._value == 1:
                 return b
             # a, b = a, b
-        elif sb: # a * 1 = a
+        elif sb:  # a * 1 = a
             if b._value == 1:
                 return a
             a, b = b, a
-        #elif a == b: # a * a = a**2 # TODO: Why? Maybe just remove this?
+        # elif a == b: # a * a = a**2 # TODO: Why? Maybe just remove this?
         #    if not a.ufl_free_indices:
         #        return a**2
-        else: # a * b = b * a
+        else:  # a * b = b * a
             # Sort operands in a semi-canonical order
             # (NB! This is fragile! Small changes here can have large effects.)
             a, b = sorted_expr((a, b))
@@ -178,8 +182,10 @@ class Product(Operator):
         self.ufl_operands = (a, b)
 
         # Extract indices
-        fi, fid = merge_unique_indices(a.ufl_free_indices, a.ufl_index_dimensions,
-                                       b.ufl_free_indices, b.ufl_index_dimensions)
+        fi, fid = merge_unique_indices(a.ufl_free_indices,
+                                       a.ufl_index_dimensions,
+                                       b.ufl_free_indices,
+                                       b.ufl_index_dimensions)
         self.ufl_free_indices = fi
         self.ufl_index_dimensions = fid
 
@@ -192,7 +198,8 @@ class Product(Operator):
         ops = self.ufl_operands
         sh = self.ufl_shape
         if sh:
-            ufl_assert(sh == ops[-1].ufl_shape, "Expecting nonscalar product operand to be the last by convention.")
+            if sh != ops[-1].ufl_shape:
+                error("Expecting nonscalar product operand to be the last by convention.")
             tmp = ops[-1].evaluate(x, mapping, component, index_values)
             ops = ops[:-1]
         else:
@@ -205,8 +212,6 @@ class Product(Operator):
         a, b = self.ufl_operands
         return " * ".join((parstr(a, self), parstr(b, self)))
 
-    def __repr__(self):
-        return "Product(%r, %r)" % self.ufl_operands
 
 @ufl_type(num_ops=2,
           inherit_indices_from_operand=0,
@@ -221,7 +226,8 @@ class Division(Operator):
 
         # Type checking
         # TODO: Enabled workaround for nonscalar division in __div__,
-        # so maybe we can keep this assertion. Some algorithms may need updating.
+        # so maybe we can keep this assertion. Some algorithms may
+        # need updating.
         if not is_ufl_scalar(a):
             error("Expecting scalar nominator in Division.")
         if not is_true_ufl_scalar(b):
@@ -233,12 +239,12 @@ class Division(Operator):
         # Simplification a/b -> a
         if isinstance(a, Zero) or (isinstance(b, ScalarValue) and b._value == 1):
             return a
-        # Simplification "literal a / literal b" -> "literal value of a/b"
-        # Avoiding integer division by casting to float
+        # Simplification "literal a / literal b" -> "literal value of
+        # a/b". Avoiding integer division by casting to float
         if isinstance(a, ScalarValue) and isinstance(b, ScalarValue):
             return as_ufl(float(a._value) / float(b._value))
         # Simplification "a / a" -> "1"
-        #if not a.ufl_free_indices and not a.ufl_shape and a == b:
+        # if not a.ufl_free_indices and not a.ufl_shape and a == b:
         #    return as_ufl(1)
 
         # Construction
@@ -252,7 +258,7 @@ class Division(Operator):
     def __init__(self, a, b):
         Operator.__init__(self)
 
-    ufl_shape = () # self.ufl_operands[0].ufl_shape
+    ufl_shape = ()  # self.ufl_operands[0].ufl_shape
 
     def evaluate(self, x, mapping, component, index_values):
         a, b = self.ufl_operands
@@ -262,10 +268,9 @@ class Division(Operator):
         return float(a) / float(b)
 
     def __str__(self):
-        return "%s / %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
+        return "%s / %s" % (parstr(self.ufl_operands[0], self),
+                            parstr(self.ufl_operands[1], self))
 
-    def __repr__(self):
-        return "Division(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
 @ufl_type(num_ops=2,
           inherit_indices_from_operand=0,
@@ -280,9 +285,9 @@ class Power(Operator):
 
         # Type checking
         if not is_true_ufl_scalar(a):
-            error("Cannot take the power of a non-scalar expression.")
+            error("Cannot take the power of a non-scalar expression %s." % ufl_err_str(a))
         if not is_true_ufl_scalar(b):
-            error("Cannot raise an expression to a non-scalar power.")
+            error("Cannot raise an expression to a non-scalar power %s." % ufl_err_str(b))
 
         # Simplification
         if isinstance(a, ScalarValue) and isinstance(b, ScalarValue):
@@ -321,8 +326,6 @@ class Power(Operator):
         a, b = self.ufl_operands
         return "%s ** %s" % (parstr(a, self), parstr(b, self))
 
-    def __repr__(self):
-        return "Power(%r, %r)" % self.ufl_operands
 
 @ufl_type(num_ops=1,
           inherit_shape_from_operand=0, inherit_indices_from_operand=0,
@@ -332,9 +335,8 @@ class Abs(Operator):
 
     def __init__(self, a):
         Operator.__init__(self, (a,))
-        ufl_assert(isinstance(a, Expr), "Expecting Expr instance.")
         if not isinstance(a, Expr):
-            error("Expecting Expr instances.")
+            error("Expecting Expr instance, not %s." % ufl_err_str(a))
 
     def evaluate(self, x, mapping, component, index_values):
         a = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
@@ -343,6 +345,3 @@ class Abs(Operator):
     def __str__(self):
         a, = self.ufl_operands
         return "|%s|" % (parstr(a, self),)
-
-    def __repr__(self):
-        return "Abs(%r)" % self.ufl_operands
diff --git a/ufl/algorithms/__init__.py b/ufl/algorithms/__init__.py
index 7efdea8..fab1ff4 100644
--- a/ufl/algorithms/__init__.py
+++ b/ufl/algorithms/__init__.py
@@ -1,7 +1,8 @@
 # -*- coding: utf-8 -*-
+# flake8: noqa
 "This module collects algorithms and utility functions operating on UFL objects."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,17 +22,59 @@
 # Modified by Anders Logg, 2008-2009.
 
 
-# FIXME: Clean up this to become a more official set of supported algorithms.
-#        Currently contains too much stuff that's not recommended to use.
-
+# FIXME: Clean up this to become a more official set of supported
+#        algorithms.  Currently contains too much stuff that's not
+#        recommended to use. The __all__ list below is a start based
+#        on grepping of other FEniCS code for ufl.algorithm imports.
+
+from ufl.utils.py23 import as_native_strings
+
+__all__ = as_native_strings([
+    "estimate_total_polynomial_degree",
+    "sort_elements",
+    "compute_form_data",
+    "purge_list_tensors",
+    "apply_transformer",
+    "ReuseTransformer",
+    "load_ufl_file",
+    "Transformer",
+    "MultiFunction",
+    "extract_unique_elements",
+    "extract_type",
+    "extract_elements",
+    "extract_sub_elements",
+    "preprocess_expression",
+    "expand_indices",
+    "replace",
+    "expand_derivatives",
+    "extract_coefficients",
+    "strip_variables",
+    "post_traversal",
+    "change_to_reference_grad",
+    "expand_compounds",
+    "validate_form",
+    "ufl2latex",
+    "FormSplitter",
+    "extract_arguments",
+    "compute_form_adjoint",
+    "compute_form_action",
+    "compute_energy_norm",
+    "compute_form_lhs",
+    "compute_form_rhs",
+    "compute_form_functional",
+    "compute_form_signature",
+    "tree_format",
+    ])
 
 # Utilities for traversing over expression trees in different ways
-from ufl.algorithms.traversal import iter_expressions
+#from ufl.algorithms.traversal import iter_expressions
 
-# Keeping these imports here for backwards compatibility, doesn't cost anything.
-# Prefer importing from ufl.corealg.traversal in future code.
-from ufl.corealg.traversal import pre_traversal, post_traversal
-from ufl.corealg.traversal import traverse_terminals, traverse_unique_terminals
+# Keeping these imports here for backwards compatibility, doesn't cost
+# anything.  Prefer importing from ufl.corealg.traversal in future
+# code.
+#from ufl.corealg.traversal import pre_traversal
+from ufl.corealg.traversal import post_traversal
+#from ufl.corealg.traversal import traverse_terminals, traverse_unique_terminals
 
 
 # Utilities for extracting information from forms and expressions
@@ -39,7 +82,7 @@ from ufl.algorithms.analysis import (
     extract_type,
     extract_arguments,
     extract_coefficients,
-    extract_arguments_and_coefficients,
+    #extract_arguments_and_coefficients,
     extract_elements,
     extract_unique_elements,
     extract_sub_elements,
@@ -48,11 +91,10 @@ from ufl.algorithms.analysis import (
 
 
 # Preprocessing a form to extract various meta data
-from ufl.algorithms.formdata import FormData
+#from ufl.algorithms.formdata import FormData
 from ufl.algorithms.compute_form_data import compute_form_data
 
 # Utilities for checking properties of forms
-from ufl.algorithms.predicates import is_multilinear
 from ufl.algorithms.signature import compute_form_signature
 
 # Utilities for error checking of forms
@@ -60,22 +102,26 @@ from ufl.algorithms.checks import validate_form
 
 # Utilites for modifying expressions and forms
 from ufl.corealg.multifunction import MultiFunction
-from ufl.algorithms.transformer import Transformer, is_post_handler, \
-                                       apply_transformer, \
-                                       ReuseTransformer, \
-                                       VariableStripper, strip_variables
-from ufl.algorithms.replace import Replacer, replace
+from ufl.algorithms.transformer import Transformer, ReuseTransformer
+#from ufl.algorithms.transformer import is_post_handler
+from ufl.algorithms.transformer import apply_transformer
+from ufl.algorithms.transformer import strip_variables
+#from ufl.algorithms.replace import Replacer
+from ufl.algorithms.replace import replace
 from ufl.algorithms.change_to_reference import change_to_reference_grad
 from ufl.algorithms.expand_compounds import expand_compounds
-from ufl.algorithms.estimate_degrees import SumDegreeEstimator, estimate_total_polynomial_degree
-from ufl.algorithms.argument_dependencies import ArgumentDependencyExtracter, extract_argument_dependencies, NotMultiLinearException
+#from ufl.algorithms.estimate_degrees import SumDegreeEstimator
+from ufl.algorithms.estimate_degrees import estimate_total_polynomial_degree
 from ufl.algorithms.expand_indices import expand_indices, purge_list_tensors
 
 # Utilities for transforming complete Forms into other Forms
-from ufl.algorithms.formtransformations import (
-    compute_form_adjoint, compute_form_action, compute_energy_norm,
-    compute_form_lhs, compute_form_rhs,
-    compute_form_functional, compute_form_arities)
+from ufl.algorithms.formtransformations import compute_form_adjoint
+from ufl.algorithms.formtransformations import compute_form_action
+from ufl.algorithms.formtransformations import compute_energy_norm
+from ufl.algorithms.formtransformations import compute_form_lhs
+from ufl.algorithms.formtransformations import compute_form_rhs
+from ufl.algorithms.formtransformations import compute_form_functional
+from ufl.algorithms.formtransformations import compute_form_arities
 
 from ufl.algorithms.formsplitter import FormSplitter
 
@@ -83,10 +129,11 @@ from ufl.algorithms.formsplitter import FormSplitter
 from ufl.algorithms.ad import expand_derivatives
 
 # Utilities for form file handling
-from ufl.algorithms.formfiles import read_ufl_file, load_ufl_file, load_forms
-
+from ufl.algorithms.formfiles import read_ufl_file
+from ufl.algorithms.formfiles import load_ufl_file
+from ufl.algorithms.formfiles import load_forms
 
 # Utilities for UFL object printing
-from ufl.formatting.printing import integral_info, form_info, tree_format
-from ufl.formatting.ufl2latex import ufl2latex, ufl2tex, ufl2pdf, forms2latexdocument
-from ufl.formatting.ufl2dot import ufl2dot
+#from ufl.formatting.printing import integral_info, form_info
+from ufl.formatting.printing import tree_format
+from ufl.formatting.ufl2latex import ufl2latex
diff --git a/ufl/algorithms/ad.py b/ufl/algorithms/ad.py
index a2e57d3..9f17098 100644
--- a/ufl/algorithms/ad.py
+++ b/ufl/algorithms/ad.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Front-end for AD routines."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -24,6 +24,7 @@ from ufl.log import warning
 from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
 from ufl.algorithms.apply_derivatives import apply_derivatives
 
+
 def expand_derivatives(form, **kwargs):
     """Expand all derivatives of expr.
 
@@ -32,7 +33,8 @@ def expand_derivatives(form, **kwargs):
     or CoefficientDerivative objects left, and Grad
     objects have been propagated to Terminal nodes.
     """
-    # For a deprecation period (I see that dolfin-adjoint passes some args here)
+    # For a deprecation period (I see that dolfin-adjoint passes some
+    # args here)
     if kwargs:
         warning("Deprecation: expand_derivatives no longer takes any keyword arguments")
 
diff --git a/ufl/algorithms/analysis.py b/ufl/algorithms/analysis.py
index 96ce18d..7665028 100644
--- a/ufl/algorithms/analysis.py
+++ b/ufl/algorithms/analysis.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Utility algorithms for inspection of and information extraction from UFL objects in various ways."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -22,28 +22,19 @@
 # Modified by Johan Hake, 2010.
 
 from itertools import chain
-from six.moves import zip
-from collections import namedtuple
 
-from ufl.log import error, warning, info
-from ufl.assertions import ufl_assert
+from ufl.log import error
 from ufl.utils.sorting import sorted_by_count, topological_sorting
 
-from ufl.core.expr import Expr
 from ufl.core.terminal import Terminal, FormArgument
-from ufl.finiteelement import MixedElement, RestrictedElement
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
-from ufl.variable import Variable
-from ufl.core.multiindex import Index, MultiIndex
-from ufl.integral import Measure, Integral
-from ufl.form import Form
 from ufl.algorithms.traversal import iter_expressions
 from ufl.corealg.traversal import unique_pre_traversal, traverse_unique_terminals
 
 
-# TODO: Some of these can possibly be optimised by implementing inlined stack based traversal algorithms
-
+# TODO: Some of these can possibly be optimised by implementing
+# inlined stack based traversal algorithms
 
 def _sorted_by_number_and_part(seq):
     return sorted(seq, key=lambda x: (x.number(), x.part()))
@@ -60,7 +51,7 @@ def unique_tuple(objects):
     return tuple(unique_objects)
 
 
-#--- Utilities to extract information from an expression ---
+# --- Utilities to extract information from an expression ---
 
 def __unused__extract_classes(a):
     """Build a set of all unique Expr subclasses used in a.
@@ -69,6 +60,7 @@ def __unused__extract_classes(a):
                for e in iter_expressions(a)
                for o in unique_pre_traversal(e))
 
+
 def extract_type(a, ufl_type):
     """Build a set of all objects of class ufl_type found in a.
     The argument a can be a Form, Integral or Expr."""
@@ -82,6 +74,7 @@ def extract_type(a, ufl_type):
                    for o in unique_pre_traversal(e)
                    if isinstance(o, ufl_type))
 
+
 def has_type(a, ufl_type):
     """Return if an object of class ufl_type can be found in a.
     The argument a can be a Form, Integral or Expr."""
@@ -92,6 +85,7 @@ def has_type(a, ufl_type):
         traversal = unique_pre_traversal
     return any(isinstance(o, ufl_type) for e in iter_expressions(a) for o in traversal(e))
 
+
 def has_exact_type(a, ufl_type):
     """Return if an object of class ufl_type can be found in a.
     The argument a can be a Form, Integral or Expr."""
@@ -103,16 +97,19 @@ def has_exact_type(a, ufl_type):
         traversal = unique_pre_traversal
     return any(o._ufl_typecode_ == tc for e in iter_expressions(a) for o in traversal(e))
 
+
 def extract_arguments(a):
     """Build a sorted list of all arguments in a,
     which can be a Form, Integral or Expr."""
     return _sorted_by_number_and_part(extract_type(a, Argument))
 
+
 def extract_coefficients(a):
     """Build a sorted list of all coefficients in a,
     which can be a Form, Integral or Expr."""
     return sorted_by_count(extract_type(a, Coefficient))
 
+
 def extract_arguments_and_coefficients(a):
     """Build two sorted lists of all arguments and coefficients
     in a, which can be a Form, Integral or Expr."""
@@ -168,22 +165,6 @@ def extract_sub_elements(elements):
     return tuple(elements) + extract_sub_elements(sub_elements)
 
 
-def __unused__extract_unique_sub_elements(elements):
-    "Build sorted tuple of all unique sub elements (including parent element)."
-    return unique_tuple(extract_sub_elements(elements))
-
-
-def __unused__extract_element_map(elements):
-    "Build map from elements to element index in ordered tuple."
-    element_map = {}
-    unique_elements = unique_tuple(elements)
-    for element in elements:
-        indices = [i for (i, e) in enumerate(unique_elements) if e == element]
-        ufl_assert(len(indices) == 1, "Unable to find unique index for element.")
-        element_map[element] = i
-    return element_map
-
-
 def sort_elements(elements):
     """
     Sort elements so that any sub elements appear before the
diff --git a/ufl/algorithms/apply_algebra_lowering.py b/ufl/algorithms/apply_algebra_lowering.py
index 6e934c6..f65364d 100644
--- a/ufl/algorithms/apply_algebra_lowering.py
+++ b/ufl/algorithms/apply_algebra_lowering.py
@@ -2,7 +2,7 @@
 """Algorithm for expanding compound expressions into
 equivalent representations using basic operators."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -21,14 +21,13 @@ equivalent representations using basic operators."""
 #
 # Modified by Anders Logg, 2009-2010
 
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
+from ufl.log import error
 
 from ufl.classes import Product, Grad
 from ufl.core.multiindex import indices, Index, FixedIndex
 from ufl.tensors import as_tensor, as_matrix, as_vector
 
-from ufl.compound_expressions import deviatoric_expr, determinant_expr, cofactor_expr, adj_expr, inverse_expr
+from ufl.compound_expressions import deviatoric_expr, determinant_expr, cofactor_expr, inverse_expr
 
 from ufl.corealg.multifunction import MultiFunction
 from ufl.algorithms.map_integrands import map_integrand_dags
@@ -54,8 +53,10 @@ class LowerCompoundAlgebra(MultiFunction):
 
     def _square_matrix_shape(self, A):
         sh = A.ufl_shape
-        ufl_assert(sh[0] == sh[1], "Expecting square matrix.")
-        ufl_assert(sh[0] is not None, "Unknown dimension.")
+        if sh[0] != sh[1]:
+            error("Expecting square matrix.")
+        if sh[0] is None:
+            error("Unknown dimension.")
         return sh
 
     def deviatoric(self, o, A):
@@ -63,23 +64,24 @@ class LowerCompoundAlgebra(MultiFunction):
 
     def skew(self, o, A):
         i, j = indices(2)
-        return as_matrix( (A[i, j] - A[j, i]) / 2, (i, j) )
+        return as_matrix((A[i, j] - A[j, i]) / 2, (i, j))
 
     def sym(self, o, A):
         i, j = indices(2)
-        return as_matrix( (A[i, j] + A[j, i]) / 2, (i, j) )
+        return as_matrix((A[i, j] + A[j, i]) / 2, (i, j))
 
     def cross(self, o, a, b):
         def c(i, j):
             return Product(a[i], b[j]) - Product(a[j], b[i])
         return as_vector((c(1, 2), c(2, 0), c(0, 1)))
 
-    def altenative_dot(self, o, a, b): # TODO: Test this
+    def altenative_dot(self, o, a, b):  # TODO: Test this
         ash = a.ufl_shape
         bsh = b.ufl_shape
-        ai = indices(len(ash)-1)
-        bi = indices(len(bsh)-1)
-        # Simplification for tensors where the dot-sum dimension has length 1
+        ai = indices(len(ash) - 1)
+        bi = indices(len(bsh) - 1)
+        # Simplification for tensors where the dot-sum dimension has
+        # length 1
         if ash[-1] == 1:
             k = (FixedIndex(0),)
         else:
@@ -96,11 +98,13 @@ class LowerCompoundAlgebra(MultiFunction):
         s = a[ai+k]*b[k+bi]
         return as_tensor(s, ai+bi)
 
-    def alternative_inner(self, o, a, b): # TODO: Test this
+    def alternative_inner(self, o, a, b):  # TODO: Test this
         ash = a.ufl_shape
         bsh = b.ufl_shape
-        ufl_assert(ash == bsh)
-        # Simplification for tensors with one or more dimensions of length 1
+        if ash != bsh:
+            error("Nonmatching shapes.")
+        # Simplification for tensors with one or more dimensions of
+        # length 1
         ii = []
         zi = FixedIndex(0)
         for n in ash:
@@ -109,14 +113,17 @@ class LowerCompoundAlgebra(MultiFunction):
             else:
                 ii.append(Index())
         ii = tuple(ii)
-        #ii = indices(len(a.ufl_shape))
+        # ii = indices(len(a.ufl_shape))
         # Potentially creates multiple IndexSums over a Product
         s = a[ii]*b[ii]
         return s
 
     def inner(self, o, a, b):
-        ufl_assert(a.ufl_shape == b.ufl_shape)
-        ii = indices(len(a.ufl_shape))
+        ash = a.ufl_shape
+        bsh = b.ufl_shape
+        if ash != bsh:
+            error("Nonmatching shapes.")
+        ii = indices(len(ash))
         # Creates multiple IndexSums over a Product
         s = a[ii]*b[ii]
         return s
diff --git a/ufl/algorithms/apply_derivatives.py b/ufl/algorithms/apply_derivatives.py
index 82d59d1..287c8cb 100644
--- a/ufl/algorithms/apply_derivatives.py
+++ b/ufl/algorithms/apply_derivatives.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module contains the apply_derivatives algorithm which computes the derivatives of a form of expression."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,11 +19,11 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 
-from ufl.assertions import ufl_assert
-from ufl.log import error
+from ufl.log import error, warning
 
+from ufl.core.expr import ufl_err_str
 from ufl.core.terminal import Terminal
-from ufl.core.multiindex import MultiIndex, Index, FixedIndex, indices
+from ufl.core.multiindex import MultiIndex, FixedIndex, indices
 
 from ufl.tensors import as_tensor, as_scalar, as_scalars, unit_indexed_tensor, unwrap_list_tensor
 
@@ -33,14 +33,14 @@ from ufl.classes import Grad, ReferenceGrad, Variable
 from ufl.classes import Indexed, ListTensor, ComponentTensor
 from ufl.classes import ExprList, ExprMapping
 from ufl.classes import Product, Sum, IndexSum
-from ufl.classes import Jacobian, JacobianInverse
+from ufl.classes import JacobianInverse
 from ufl.classes import SpatialCoordinate
 
 from ufl.constantvalue import is_true_ufl_scalar, is_ufl_scalar
-from ufl.operators import (dot, inner, outer, lt, eq, conditional, sign,
-    sqrt, exp, ln, cos, sin, tan, cosh, sinh, tanh, acos, asin, atan, atan_2,
-    erf, bessel_J, bessel_Y, bessel_I, bessel_K,
-    cell_avg, facet_avg)
+from ufl.operators import (conditional, sign,
+                           sqrt, exp, ln, cos, sin, cosh, sinh,
+                           bessel_J, bessel_Y, bessel_I, bessel_K,
+                           cell_avg, facet_avg)
 
 from math import pi
 
@@ -68,7 +68,6 @@ class GenericDerivativeRuleset(MultiFunction):
         MultiFunction.__init__(self)
         self._var_shape = var_shape
 
-
     # --- Error checking for missing handlers and unexpected types
 
     def expr(self, o):
@@ -86,8 +85,8 @@ class GenericDerivativeRuleset(MultiFunction):
     def fixme(self, o):
         error("FIXME: Unimplemented differentiation handler for type {0}.".format(o._ufl_class_.__name__))
 
-
-    # --- Some types just don't have any derivative, this is just to make algorithm structure generic
+    # --- Some types just don't have any derivative, this is just to
+    # --- make algorithm structure generic
 
     def non_differentiable_terminal(self, o):
         "Labels and indices are not differentiable. It's convenient to return the non-differentiated object."
@@ -124,49 +123,49 @@ class GenericDerivativeRuleset(MultiFunction):
 
     # These types are currently assumed independent, but for non-affine domains
     # this no longer holds and we want to implement rules for them.
-    #facet_normal = independent_terminal
-    #spatial_coordinate = independent_terminal
-    #cell_coordinate = independent_terminal
+    # facet_normal = independent_terminal
+    # spatial_coordinate = independent_terminal
+    # cell_coordinate = independent_terminal
 
     # Measures of cell entities, assuming independent although
     # this will not be true for all of these for non-affine domains
-    #cell_volume = independent_terminal
-    #circumradius = independent_terminal
-    #facet_area = independent_terminal
-    #cell_surface_area = independent_terminal
-    #min_cell_edge_length = independent_terminal
-    #max_cell_edge_length = independent_terminal
-    #min_facet_edge_length = independent_terminal
-    #max_facet_edge_length = independent_terminal
+    # cell_volume = independent_terminal
+    # circumradius = independent_terminal
+    # facet_area = independent_terminal
+    # cell_surface_area = independent_terminal
+    # min_cell_edge_length = independent_terminal
+    # max_cell_edge_length = independent_terminal
+    # min_facet_edge_length = independent_terminal
+    # max_facet_edge_length = independent_terminal
 
     # Other stuff
-    #cell_orientation = independent_terminal
-    #quadrature_weigth = independent_terminal
+    # cell_orientation = independent_terminal
+    # quadrature_weigth = independent_terminal
 
     # These types are currently not expected to show up in AD pass.
-    # To make some of these available to the end-user, they need to be implemented here.
-    #facet_coordinate = unexpected
-    #cell_origin = unexpected
-    #facet_origin = unexpected
-    #cell_facet_origin = unexpected
-    #jacobian = unexpected
-    #jacobian_determinant = unexpected
-    #jacobian_inverse = unexpected
-    #facet_jacobian = unexpected
-    #facet_jacobian_determinant = unexpected
-    #facet_jacobian_inverse = unexpected
-    #cell_facet_jacobian = unexpected
-    #cell_facet_jacobian_determinant = unexpected
-    #cell_facet_jacobian_inverse = unexpected
-    #cell_edge_vectors = unexpected
-    #facet_edge_vectors = unexpected
-    #cell_normal = unexpected # TODO: Expecting rename
-    #cell_normals = unexpected
-    #facet_tangents = unexpected
-    #cell_tangents = unexpected
-    #cell_midpoint = unexpected
-    #facet_midpoint = unexpected
-
+    # To make some of these available to the end-user, they need to be
+    # implemented here.
+    # facet_coordinate = unexpected
+    # cell_origin = unexpected
+    # facet_origin = unexpected
+    # cell_facet_origin = unexpected
+    # jacobian = unexpected
+    # jacobian_determinant = unexpected
+    # jacobian_inverse = unexpected
+    # facet_jacobian = unexpected
+    # facet_jacobian_determinant = unexpected
+    # facet_jacobian_inverse = unexpected
+    # cell_facet_jacobian = unexpected
+    # cell_facet_jacobian_determinant = unexpected
+    # cell_facet_jacobian_inverse = unexpected
+    # cell_edge_vectors = unexpected
+    # facet_edge_vectors = unexpected
+    # cell_normal = unexpected # TODO: Expecting rename
+    # cell_normals = unexpected
+    # facet_tangents = unexpected
+    # cell_tangents = unexpected
+    # cell_midpoint = unexpected
+    # facet_midpoint = unexpected
 
     # --- Default rules for operators
 
@@ -175,12 +174,13 @@ class GenericDerivativeRuleset(MultiFunction):
 
     # --- Indexing and component handling
 
-    def indexed(self, o, Ap, ii): # TODO: (Partially) duplicated in nesting rules
+    def indexed(self, o, Ap, ii):  # TODO: (Partially) duplicated in nesting rules
         # Propagate zeros
         if isinstance(Ap, Zero):
             return self.independent_operator(o)
 
-        # Untangle as_tensor(C[kk], jj)[ii] -> C[ll] to simplify resulting expression
+        # Untangle as_tensor(C[kk], jj)[ii] -> C[ll] to simplify
+        # resulting expression
         if isinstance(Ap, ComponentTensor):
             B, jj = Ap.ufl_operands
             if isinstance(B, Indexed):
@@ -222,7 +222,8 @@ class GenericDerivativeRuleset(MultiFunction):
         return da + db
 
     def product(self, o, da, db):
-        # Even though arguments to o are scalar, da and db may be tensor valued
+        # Even though arguments to o are scalar, da and db may be
+        # tensor valued
         a, b = o.ufl_operands
         (da, db), ii = as_scalars(da, db)
         pa = Product(da, b)
@@ -235,15 +236,18 @@ class GenericDerivativeRuleset(MultiFunction):
     def division(self, o, fp, gp):
         f, g = o.ufl_operands
 
-        ufl_assert(is_ufl_scalar(f), "Not expecting nonscalar nominator")
-        ufl_assert(is_true_ufl_scalar(g), "Not expecting nonscalar denominator")
+        if not is_ufl_scalar(f):
+            error("Not expecting nonscalar nominator")
+        if not is_true_ufl_scalar(g):
+            error("Not expecting nonscalar denominator")
 
-        #do_df = 1/g
-        #do_dg = -h/g
-        #op = do_df*fp + do_df*gp
-        #op = (fp - o*gp) / g
+        # do_df = 1/g
+        # do_dg = -h/g
+        # op = do_df*fp + do_df*gp
+        # op = (fp - o*gp) / g
 
-        # Get o and gp as scalars, multiply, then wrap as a tensor again
+        # Get o and gp as scalars, multiply, then wrap as a tensor
+        # again
         so, oi = as_scalar(o)
         sgp, gi = as_scalar(gp)
         o_gp = so * sgp
@@ -256,43 +260,47 @@ class GenericDerivativeRuleset(MultiFunction):
     def power(self, o, fp, gp):
         f, g = o.ufl_operands
 
-        ufl_assert(is_true_ufl_scalar(f), "Expecting scalar expression f in f**g.")
-        ufl_assert(is_true_ufl_scalar(g), "Expecting scalar expression g in f**g.")
+        if not is_true_ufl_scalar(f):
+            error("Expecting scalar expression f in f**g.")
+        if not is_true_ufl_scalar(g):
+            error("Expecting scalar expression g in f**g.")
 
         # Derivation of the general case: o = f(x)**g(x)
-        #do/df  = g * f**(g-1) = g / f * o
-        #do/dg  = ln(f) * f**g = ln(f) * o
-        #do/df * df + do/dg * dg = o * (g / f * df + ln(f) * dg)
+        # do/df  = g * f**(g-1) = g / f * o
+        # do/dg  = ln(f) * f**g = ln(f) * o
+        # do/df * df + do/dg * dg = o * (g / f * df + ln(f) * dg)
 
         if isinstance(gp, Zero):
-            # This probably produces better results for the common case of f**constant
+            # This probably produces better results for the common
+            # case of f**constant
             op = fp * g * f**(g-1)
         else:
             # Note: This produces expressions like (1/w)*w**5 instead of w**4
-            #op = o * (fp * g / f + gp * ln(f)) # This reuses o
-            op = f**(g-1) * (g*fp + f*ln(f)*gp) # This gives better accuracy in dolfin integration test
+            # op = o * (fp * g / f + gp * ln(f)) # This reuses o
+            op = f**(g-1) * (g*fp + f*ln(f)*gp)  # This gives better accuracy in dolfin integration test
 
         # Example: d/dx[x**(x**3)]:
-        #f = x
-        #g = x**3
-        #df = 1
-        #dg = 3*x**2
-        #op1 = o * (fp * g / f + gp * ln(f))
-        #    = x**(x**3)   * (x**3/x + 3*x**2*ln(x))
-        #op2 = f**(g-1) * (g*fp + f*ln(f)*gp)
-        #    = x**(x**3-1) * (x**3 + x*3*x**2*ln(x))
+        # f = x
+        # g = x**3
+        # df = 1
+        # dg = 3*x**2
+        # op1 = o * (fp * g / f + gp * ln(f))
+        #     = x**(x**3)   * (x**3/x + 3*x**2*ln(x))
+        # op2 = f**(g-1) * (g*fp + f*ln(f)*gp)
+        #     = x**(x**3-1) * (x**3 + x*3*x**2*ln(x))
 
         return op
 
     def abs(self, o, df):
         f, = o.ufl_operands
-        #return conditional(eq(f, 0), 0, Product(sign(f), df))
+        # return conditional(eq(f, 0), 0, Product(sign(f), df))
         return sign(f) * df
 
     # --- Mathfunctions
 
     def math_function(self, o, df):
-        # FIXME: Introduce a UserOperator type instead of this hack and define user derivative() function properly
+        # FIXME: Introduce a UserOperator type instead of this hack
+        # and define user derivative() function properly
         if hasattr(o, 'derivative'):
             f, = o.ufl_operands
             return df * o.derivative()
@@ -306,7 +314,8 @@ class GenericDerivativeRuleset(MultiFunction):
 
     def ln(self, o, fp):
         f, = o.ufl_operands
-        ufl_assert(not isinstance(f, Zero), "Division by zero.")
+        if isinstance(f, Zero):
+            error("Division by zero.")
         return fp / f
 
     def cos(self, o, fp):
@@ -331,6 +340,7 @@ class GenericDerivativeRuleset(MultiFunction):
 
     def tanh(self, o, fp):
         f, = o.ufl_operands
+
         def sech(y):
             return (2.0*cosh(y)) / (cosh(2.0*y) + 1.0)
         return fp * sech(f)**2
@@ -406,9 +416,9 @@ class GenericDerivativeRuleset(MultiFunction):
     def restricted(self, o, fp):
         # Restriction and differentiation commutes
         if isinstance(fp, ConstantValue):
-            return fp # TODO: Add simplification to Restricted instead?
+            return fp  # TODO: Add simplification to Restricted instead?
         else:
-            return fp(o._side) # (f+-)' == (f')+-
+            return fp(o._side)  # (f+-)' == (f')+-
 
     # --- Conditionals
 
@@ -423,34 +433,39 @@ class GenericDerivativeRuleset(MultiFunction):
     def conditional(self, o, unused_dc, dt, df):
         global CONDITIONAL_WORKAROUND
         if isinstance(dt, Zero) and isinstance(df, Zero):
-            # Assuming dt and df have the same indices here, which should be the case
+            # Assuming dt and df have the same indices here, which
+            # should be the case
             return dt
         elif CONDITIONAL_WORKAROUND:
-            # Placing t[1],f[1] outside here to avoid getting arguments inside conditionals.
-            # This will fail when dt or df become NaN or Inf in floating point computations!
+            # Placing t[1],f[1] outside here to avoid getting
+            # arguments inside conditionals.  This will fail when dt
+            # or df become NaN or Inf in floating point computations!
             c = o.ufl_operands[0]
             dc = conditional(c, 1, 0)
             return dc*dt + (1.0 - dc)*df
         else:
-            # Not placing t[1],f[1] outside, allowing arguments inside conditionals.
-            # This will make legacy ffc fail, but should work with uflacs.
+            # Not placing t[1],f[1] outside, allowing arguments inside
+            # conditionals.  This will make legacy ffc fail, but
+            # should work with uflacs.
             c = o.ufl_operands[0]
             return conditional(c, dt, df)
 
     def max_value(self, o, df, dg):
-        #d/dx max(f, g) =
+        # d/dx max(f, g) =
         # f > g: df/dx
         # f < g: dg/dx
-        # Placing df,dg outside here to avoid getting arguments inside conditionals
+        # Placing df,dg outside here to avoid getting arguments inside
+        # conditionals
         f, g = o.ufl_operands
         dc = conditional(f > g, 1, 0)
         return dc*df + (1.0 - dc)*dg
 
     def min_value(self, o, df, dg):
-        #d/dx min(f, g) =
-        # f < g: df/dx
-        # else: dg/dx
-        # Placing df,dg outside here to avoid getting arguments inside conditionals
+        # d/dx min(f, g) =
+        #  f < g: df/dx
+        #  else: dg/dx
+        #  Placing df,dg outside here to avoid getting arguments
+        #  inside conditionals
         f, g = o.ufl_operands
         dc = conditional(f < g, 1, 0)
         return dc*df + (1.0 - dc)*dg
@@ -469,20 +484,23 @@ class GradRuleset(GenericDerivativeRuleset):
         if is_cellwise_constant(o):
             return self.independent_terminal(o)
         else:
-            # TODO: Which types does this involve? I don't think the form compilers will handle this.
+            # TODO: Which types does this involve? I don't think the
+            # form compilers will handle this.
             return Grad(o)
 
     def jacobian_inverse(self, o):
         # grad(K) == K_ji rgrad(K)_rj
         if is_cellwise_constant(o):
             return self.independent_terminal(o)
-        ufl_assert(o._ufl_is_terminal_, "ReferenceValue can only wrap a terminal")
+        if not o._ufl_is_terminal_:
+            error("ReferenceValue can only wrap a terminal")
         r = indices(len(o.ufl_shape))
         i, j = indices(2)
-        Do = as_tensor(o[j,i]*ReferenceGrad(o)[r + (j,)], r + (i,))
+        Do = as_tensor(o[j, i]*ReferenceGrad(o)[r + (j,)], r + (i,))
         return Do
 
-    # TODO: Add more explicit geometry type handlers here, with non-affine domains several should be non-zero.
+    # TODO: Add more explicit geometry type handlers here, with
+    # non-affine domains several should be non-zero.
 
     def spatial_coordinate(self, o):
         "dx/dx = I"
@@ -501,38 +519,39 @@ class GradRuleset(GenericDerivativeRuleset):
         return Grad(o)
 
     def argument(self, o):
+        # TODO: Enable this after fixing issue#13, unless we move
+        # simplificat ion to a separate stage?
+        # if is_cellwise_constant(o):
+        #     # Collapse gradient of cellwise constant function to zero
+        #     # TODO: Missing this type
+        #     return AnnotatedZero(o.ufl_shape + self._var_shape, arguments=(o,))
         return Grad(o)
 
-    def _argument(self, o): # TODO: Enable this after fixing issue#13, unless we move simplification to a separate stage?
-        if is_cellwise_constant(o):
-            # Collapse gradient of cellwise constant function to zero
-            return AnnotatedZero(o.ufl_shape + self._var_shape, arguments=(o,)) # TODO: Missing this type
-        else:
-            return Grad(o)
-
     # --- Rules for values or derivatives in reference frame
 
     def reference_value(self, o):
         # grad(o) == grad(rv(f)) -> K_ji*rgrad(rv(f))_rj
         f = o.ufl_operands[0]
-        ufl_assert(f._ufl_is_terminal_, "ReferenceValue can only wrap a terminal")
+        if not f._ufl_is_terminal_:
+            error("ReferenceValue can only wrap a terminal")
         domain = f.ufl_domain()
         K = JacobianInverse(domain)
         r = indices(len(o.ufl_shape))
         i, j = indices(2)
-        Do = as_tensor(K[j,i]*ReferenceGrad(o)[r + (j,)], r + (i,))
+        Do = as_tensor(K[j, i]*ReferenceGrad(o)[r + (j,)], r + (i,))
         return Do
 
     def reference_grad(self, o):
         # grad(o) == grad(rgrad(rv(f))) -> K_ji*rgrad(rgrad(rv(f)))_rj
         f = o.ufl_operands[0]
         valid_operand = f._ufl_is_in_reference_frame_ or isinstance(f, (JacobianInverse, SpatialCoordinate))
-        ufl_assert(valid_operand, "ReferenceGrad can only wrap a reference frame type!")
+        if not valid_operand:
+            error("ReferenceGrad can only wrap a reference frame type!")
         domain = f.ufl_domain()
         K = JacobianInverse(domain)
         r = indices(len(o.ufl_shape))
         i, j = indices(2)
-        Do = as_tensor(K[j,i]*ReferenceGrad(o)[r + (j,)], r + (i,))
+        Do = as_tensor(K[j, i]*ReferenceGrad(o)[r + (j,)], r + (i,))
         return Do
 
     # --- Nesting of gradients
@@ -541,8 +560,8 @@ class GradRuleset(GenericDerivativeRuleset):
         "Represent grad(grad(f)) as Grad(Grad(f))."
 
         # Check that o is a "differential terminal"
-        ufl_assert(isinstance(o.ufl_operands[0], (Grad, Terminal)),
-                   "Expecting only grads applied to a terminal.")
+        if not isinstance(o.ufl_operands[0], (Grad, Terminal)):
+            error("Expecting only grads applied to a terminal.")
 
         return Grad(o)
 
@@ -550,8 +569,8 @@ class GradRuleset(GenericDerivativeRuleset):
         pass
         # TODO: Not sure how to detect that gradient of f is cellwise constant.
         #       Can we trust element degrees?
-        #if is_cellwise_constant(o):
-        #    return self.terminal(o)
+        # if is_cellwise_constant(o):
+        #     return self.terminal(o)
         # TODO: Maybe we can ask "f.has_derivatives_of_order(n)" to check
         #       if we should make a zero here?
         # 1) n = count number of Grads, get f
@@ -563,7 +582,8 @@ class GradRuleset(GenericDerivativeRuleset):
 
 class ReferenceGradRuleset(GenericDerivativeRuleset):
     def __init__(self, topological_dimension):
-        GenericDerivativeRuleset.__init__(self, var_shape=(topological_dimension,))
+        GenericDerivativeRuleset.__init__(self,
+                                          var_shape=(topological_dimension,))
         self._Id = Identity(topological_dimension)
 
     # --- Specialized rules for geometric quantities
@@ -573,7 +593,8 @@ class ReferenceGradRuleset(GenericDerivativeRuleset):
         if is_cellwise_constant(o):
             return self.independent_terminal(o)
         else:
-            # TODO: Which types does this involve? I don't think the form compilers will handle this.
+            # TODO: Which types does this involve? I don't think the
+            # form compilers will handle this.
             return ReferenceGrad(o)
 
     def spatial_coordinate(self, o):
@@ -585,27 +606,22 @@ class ReferenceGradRuleset(GenericDerivativeRuleset):
         "dX/dX = I"
         return self._Id
 
-    # TODO: Add more geometry types here, with non-affine domains several should be non-zero.
+    # TODO: Add more geometry types here, with non-affine domains
+    # several should be non-zero.
 
     # --- Specialized rules for form arguments
 
+    def reference_value(self, o):
+        if not o.ufl_operands[0]._ufl_is_terminal_:
+            error("ReferenceValue can only wrap a terminal")
+        return ReferenceGrad(o)
+
     def coefficient(self, o):
         error("Coefficient should be wrapped in ReferenceValue by now")
 
     def argument(self, o):
         error("Argument should be wrapped in ReferenceValue by now")
 
-    def reference_value(self, o):
-        ufl_assert(o.ufl_operands[0]._ufl_is_terminal_, "ReferenceValue can only wrap a terminal")
-        return ReferenceGrad(o)
-
-    def _argument(self, o): # TODO: Enable this after fixing issue#13, unless we move simplification to a separate stage?
-        if is_cellwise_constant(o):
-            # Collapse gradient of cellwise constant function to zero
-            return AnnotatedZero(o.ufl_shape + self._var_shape, arguments=(o,)) # TODO: Missing this type
-        else:
-            return ReferenceGrad(o)
-
     # --- Nesting of gradients
 
     def grad(self, o):
@@ -613,11 +629,10 @@ class ReferenceGradRuleset(GenericDerivativeRuleset):
 
     def reference_grad(self, o):
         "Represent ref_grad(ref_grad(f)) as RefGrad(RefGrad(f))."
-
         # Check that o is a "differential terminal"
-        ufl_assert(isinstance(o.ufl_operands[0], (ReferenceGrad, ReferenceValue, Terminal)),
-                   "Expecting only grads applied to a terminal.")
-
+        if not isinstance(o.ufl_operands[0],
+                          (ReferenceGrad, ReferenceValue, Terminal)):
+            error("Expecting only grads applied to a terminal.")
         return ReferenceGrad(o)
 
     cell_avg = GenericDerivativeRuleset.independent_operator
@@ -627,7 +642,8 @@ class ReferenceGradRuleset(GenericDerivativeRuleset):
 class VariableRuleset(GenericDerivativeRuleset):
     def __init__(self, var):
         GenericDerivativeRuleset.__init__(self, var_shape=var.ufl_shape)
-        ufl_assert(not var.ufl_free_indices, "Differentiation variable cannot have free indices.")
+        if var.ufl_free_indices:
+            error("Differentiation variable cannot have free indices.")
         self._variable = var
         self._Id = self._make_identity(self._var_shape)
 
@@ -663,8 +679,9 @@ class VariableRuleset(GenericDerivativeRuleset):
 
     # Explicitly defining da/dw == 0
     argument = GenericDerivativeRuleset.independent_terminal
-    def _argument(self, o):
-        return AnnotatedZero(o.ufl_shape + self._var_shape, arguments=(o,)) # TODO: Missing this type
+
+    # def _argument(self, o):
+    #    return AnnotatedZero(o.ufl_shape + self._var_shape, arguments=(o,))  # TODO: Missing this type
 
     def coefficient(self, o):
         """df/dv = Id if v is f else 0.
@@ -693,8 +710,8 @@ class VariableRuleset(GenericDerivativeRuleset):
     def grad(self, o):
         "Variable derivative of a gradient of a terminal must be 0."
         # Check that o is a "differential terminal"
-        ufl_assert(isinstance(o.ufl_operands[0], (Grad, Terminal)),
-                   "Expecting only grads applied to a terminal.")
+        if not isinstance(o.ufl_operands[0], (Grad, Terminal)):
+            error("Expecting only grads applied to a terminal.")
         return self.independent_terminal(o)
 
     # --- Rules for values or derivatives in reference frame
@@ -717,13 +734,15 @@ class VariableRuleset(GenericDerivativeRuleset):
 
     def reference_grad(self, o):
         "Variable derivative of a gradient of a terminal must be 0."
-        ufl_assert(isinstance(o.ufl_operands[0], (ReferenceGrad, ReferenceValue)),
-                   "Unexpected argument to reference_grad.")
+        if not isinstance(o.ufl_operands[0],
+                          (ReferenceGrad, ReferenceValue)):
+            error("Unexpected argument to reference_grad.")
         return self.independent_terminal(o)
 
     cell_avg = GenericDerivativeRuleset.independent_operator
     facet_avg = GenericDerivativeRuleset.independent_operator
 
+
 class GateauxDerivativeRuleset(GenericDerivativeRuleset):
     """Apply AFD (Automatic Functional Differentiation) to expression.
 
@@ -736,16 +755,21 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
         GenericDerivativeRuleset.__init__(self, var_shape=())
 
         # Type checking
-        ufl_assert(isinstance(coefficients, ExprList), "Expecting a ExprList of coefficients.")
-        ufl_assert(isinstance(arguments, ExprList), "Expecting a ExprList of arguments.")
-        ufl_assert(isinstance(coefficient_derivatives, ExprMapping), "Expecting a coefficient-coefficient ExprMapping.")
-
-        # The coefficient(s) to differentiate w.r.t. and the argument(s) s.t. D_w[v](e) = d/dtau e(w+tau v)|tau=0
+        if not isinstance(coefficients, ExprList):
+            error("Expecting a ExprList of coefficients.")
+        if not isinstance(arguments, ExprList):
+            error("Expecting a ExprList of arguments.")
+        if not isinstance(coefficient_derivatives, ExprMapping):
+            error("Expecting a coefficient-coefficient ExprMapping.")
+
+        # The coefficient(s) to differentiate w.r.t. and the
+        # argument(s) s.t. D_w[v](e) = d/dtau e(w+tau v)|tau=0
         self._w = coefficients.ufl_operands
         self._v = arguments.ufl_operands
         self._w2v = {w: v for w, v in zip(self._w, self._v)}
 
-        # Build more convenient dict {f: df/dw} for each coefficient f where df/dw is nonzero
+        # Build more convenient dict {f: df/dw} for each coefficient f
+        # where df/dw is nonzero
         cd = coefficient_derivatives.ufl_operands
         self._cd = {cd[2*i]: cd[2*i+1] for i in range(len(cd)//2)}
 
@@ -753,11 +777,13 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
     geometric_quantity = GenericDerivativeRuleset.independent_terminal
 
     def cell_avg(self, o, fp):
-        # Cell average of a single function and differentiation commutes, D_f[v](cell_avg(f)) = cell_avg(v)
+        # Cell average of a single function and differentiation
+        # commutes, D_f[v](cell_avg(f)) = cell_avg(v)
         return cell_avg(fp)
 
     def facet_avg(self, o, fp):
-        # Facet average of a single function and differentiation commutes, D_f[v](facet_avg(f)) = facet_avg(v)
+        # Facet average of a single function and differentiation
+        # commutes, D_f[v](facet_avg(f)) = facet_avg(v)
         return facet_avg(fp)
 
     # Explicitly defining da/dw == 0
@@ -774,7 +800,8 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
         # Look for o among coefficient derivatives
         dos = self._cd.get(o)
         if dos is None:
-            # If o is not among coefficient derivatives, return do/dw=0
+            # If o is not among coefficient derivatives, return
+            # do/dw=0
             do = Zero(o.ufl_shape)
             return do
         else:
@@ -791,8 +818,8 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
             # Make sure we have a tuple to match the self._v tuple
             if not isinstance(dos, tuple):
                 dos = (dos,)
-            ufl_assert(len(dos) == len(self._v),
-                       "Got a tuple of arguments, expecting a matching tuple of coefficient derivatives.")
+            if len(dos) != len(self._v):
+                error("Got a tuple of arguments, expecting a matching tuple of coefficient derivatives.")
             dosum = Zero(o.ufl_shape)
             for do, v in zip(dos, self._v):
                 so, oi = as_scalar(do)
@@ -808,27 +835,35 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
 
     def reference_value(self, o):
         error("Currently no support for ReferenceValue in CoefficientDerivative.")
-        # TODO: This is implementable for regular derivative(M(f),f,v) but too messy
-        #       if customized coefficient derivative relations are given by the user.
-        #       We would only need this to allow the user to write derivative(...ReferenceValue...,...).
-        #f, = o.ufl_operands
-        #ufl_assert(f._ufl_is_terminal_, "ReferenceValue can only wrap terminals directly.")
-        #if f is w: # FIXME: check all cases like in coefficient
-        #    return ReferenceValue(v) # FIXME: requires that v is an Argument with the same element mapping!
-        #else:
-        #    return self.independent_terminal(o)
+        # TODO: This is implementable for regular derivative(M(f),f,v)
+        #       but too messy if customized coefficient derivative
+        #       relations are given by the user.  We would only need
+        #       this to allow the user to write
+        #       derivative(...ReferenceValue...,...).
+        # f, = o.ufl_operands
+        # if not f._ufl_is_terminal_:
+        #     error("ReferenceValue can only wrap terminals directly.")
+        # FIXME: check all cases like in coefficient
+        # if f is w:
+        #     # FIXME: requires that v is an Argument with the same element mapping!
+        #     return ReferenceValue(v)
+        # else:
+        #     return self.independent_terminal(o)
 
     def reference_grad(self, o):
         error("Currently no support for ReferenceGrad in CoefficientDerivative.")
-        # TODO: This is implementable for regular derivative(M(f),f,v) but too messy
-        #       if customized coefficient derivative relations are given by the user.
-        #       We would only need this to allow the user to write derivative(...ReferenceValue...,...).
+        # TODO: This is implementable for regular derivative(M(f),f,v)
+        #       but too messy if customized coefficient derivative
+        #       relations are given by the user.  We would only need
+        #       this to allow the user to write
+        #       derivative(...ReferenceValue...,...).
 
     def grad(self, g):
-        # If we hit this type, it has already been propagated
-        # to a coefficient (or grad of a coefficient), # FIXME: Assert this!
-        # so we need to take the gradient of the variation or return zero.
-        # Complications occur when dealing with derivatives w.r.t. single components...
+        # If we hit this type, it has already been propagated to a
+        # coefficient (or grad of a coefficient), # FIXME: Assert
+        # this!  so we need to take the gradient of the variation or
+        # return zero.  Complications occur when dealing with
+        # derivatives w.r.t. single components...
 
         # Figure out how many gradients are around the inner terminal
         ngrads = 0
@@ -837,14 +872,15 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
             o, = o.ufl_operands
             ngrads += 1
         if not isinstance(o, FormArgument):
-            error("Expecting gradient of a FormArgument, not %r" % (o,))
+            error("Expecting gradient of a FormArgument, not %s" % ufl_err_str(o))
 
         def apply_grads(f):
             for i in range(ngrads):
                 f = Grad(f)
             return f
 
-        # Find o among all w without any indexing, which makes this easy
+        # Find o among all w without any indexing, which makes this
+        # easy
         for (w, v) in zip(self._w, self._v):
             if o == w and isinstance(v, FormArgument):
                 # Case: d/dt [w + t v]
@@ -865,16 +901,17 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
                 vcomp = tuple(vcomp)
             else:
                 error("Expecting argument or component of argument.")
-            ufl_assert(all(isinstance(k, FixedIndex) for k in vcomp),
-                       "Expecting only fixed indices in variation.")
+            if not all(isinstance(k, FixedIndex) for k in vcomp):
+                error("Expecting only fixed indices in variation.")
             return vval, vcomp
 
         def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
-            # Apply gradients directly to argument vval,
-            # and get the right indexed scalar component(s)
+            # Apply gradients directly to argument vval, and get the
+            # right indexed scalar component(s)
             kk = indices(ngrads)
             Dvkk = apply_grads(vval)[vcomp+kk]
-            # Place scalar component(s) Dvkk into the right tensor positions
+            # Place scalar component(s) Dvkk into the right tensor
+            # positions
             if wshape:
                 Ejj, jj = unit_indexed_tensor(wshape, wcomp)
             else:
@@ -882,7 +919,8 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
             gprimeterm = as_tensor(Ejj*Dvkk, jj+kk)
             return gprimeterm
 
-        # Accumulate contributions from variations in different components
+        # Accumulate contributions from variations in different
+        # components
         for (w, v) in zip(self._w, self._v):
 
             # Analyse differentiation variable coefficient
@@ -903,22 +941,25 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
                             gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
 
                 else:
-                    ufl_assert(wshape == (), "Expecting scalar coefficient in this branch.")
+                    if wshape != ():
+                        error("Expecting scalar coefficient in this branch.")
                     # Case: d/dt [w + t v[...]]
                     wval, wcomp = w, ()
 
                     vval, vcomp = analyse_variation_argument(v)
-                    gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
+                    gprimesum = gprimesum + compute_gprimeterm(ngrads, vval,
+                                                               vcomp, wshape,
+                                                               wcomp)
 
-            elif isinstance(w, Indexed): # This path is tested in unit tests, but not actually used?
+            elif isinstance(w, Indexed):  # This path is tested in unit tests, but not actually used?
                 # Case: d/dt [w[...] + t v[...]]
                 # Case: d/dt [w[...] + t v]
                 wval, wcomp = w.ufl_operands
                 if not wval == o:
                     continue
                 assert isinstance(wval, FormArgument)
-                ufl_assert(all(isinstance(k, FixedIndex) for k in wcomp),
-                           "Expecting only fixed indices in differentiation variable.")
+                if not all(isinstance(k, FixedIndex) for k in wcomp):
+                    error("Expecting only fixed indices in differentiation variable.")
                 wshape = wval.ufl_shape
 
                 vval, vcomp = analyse_variation_argument(v)
@@ -927,26 +968,30 @@ class GateauxDerivativeRuleset(GenericDerivativeRuleset):
             else:
                 error("Expecting coefficient or component of coefficient.")
 
-        # FIXME: Handle other coefficient derivatives: oprimes = self._cd.get(o)
+        # FIXME: Handle other coefficient derivatives: oprimes =
+        # self._cd.get(o)
 
         if 0:
             oprimes = self._cd.get(o)
             if oprimes is None:
                 if self._cd:
-                    # TODO: Make it possible to silence this message in particular?
-                    #       It may be good to have for debugging...
+                    # TODO: Make it possible to silence this message
+                    #       in particular?  It may be good to have for
+                    #       debugging...
                     warning("Assuming d{%s}/d{%s} = 0." % (o, self._w))
             else:
                 # Make sure we have a tuple to match the self._v tuple
                 if not isinstance(oprimes, tuple):
                     oprimes = (oprimes,)
-                    ufl_assert(len(oprimes) == len(self._v), "Got a tuple of arguments, "+
-                                   "expecting a matching tuple of coefficient derivatives.")
+                    if len(oprimes) != len(self._v):
+                        error("Got a tuple of arguments, expecting a"
+                              " matching tuple of coefficient derivatives.")
 
                 # Compute dg/dw_j = dg/dw_h : v.
-                # Since we may actually have a tuple of oprimes and vs in a
-                # 'mixed' space, sum over them all to get the complete inner
-                # product. Using indices to define a non-compound inner product.
+                # Since we may actually have a tuple of oprimes and vs
+                # in a 'mixed' space, sum over them all to get the
+                # complete inner product. Using indices to define a
+                # non-compound inner product.
                 for (oprime, v) in zip(oprimes, self._v):
                     error("FIXME: Figure out how to do this with ngrads")
                     so, oi = as_scalar(oprime)
@@ -979,7 +1024,7 @@ class DerivativeRuleDispatcher(MultiFunction):
         return map_expr_dag(rules, f)
 
     def reference_grad(self, o, f):
-        rules = ReferenceGradRuleset(o.ufl_shape[-1]) # FIXME: Look over this and test better.
+        rules = ReferenceGradRuleset(o.ufl_shape[-1])  # FIXME: Look over this and test better.
         return map_expr_dag(rules, f)
 
     def variable_derivative(self, o, f, dummy_v):
@@ -991,12 +1036,13 @@ class DerivativeRuleDispatcher(MultiFunction):
         rules = GateauxDerivativeRuleset(w, v, cd)
         return map_expr_dag(rules, f)
 
-    def indexed(self, o, Ap, ii): # TODO: (Partially) duplicated in generic rules
+    def indexed(self, o, Ap, ii):  # TODO: (Partially) duplicated in generic rules
         # Reuse if untouched
         if Ap is o.ufl_operands[0]:
             return o
 
-        # Untangle as_tensor(C[kk], jj)[ii] -> C[ll] to simplify resulting expression
+        # Untangle as_tensor(C[kk], jj)[ii] -> C[ll] to simplify
+        # resulting expression
         if isinstance(Ap, ComponentTensor):
             B, jj = Ap.ufl_operands
             if isinstance(B, Indexed):
diff --git a/ufl/algorithms/apply_function_pullbacks.py b/ufl/algorithms/apply_function_pullbacks.py
index 9a90ee2..a22e0c2 100644
--- a/ufl/algorithms/apply_function_pullbacks.py
+++ b/ufl/algorithms/apply_function_pullbacks.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithm for replacing gradients in an expression with reference gradients and coordinate mappings."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -17,11 +17,13 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Lizao Li <lzlarryli at gmail.com>, 2016
+
 
 from six.moves import xrange as range
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
 
 from ufl.core.multiindex import indices
 from ufl.corealg.multifunction import MultiFunction, memoized_handler
@@ -31,14 +33,10 @@ from ufl.classes import (ReferenceValue,
                          Jacobian, JacobianInverse, JacobianDeterminant,
                          Index)
 
-from ufl.constantvalue import as_ufl, Identity
 from ufl.tensors import as_tensor, as_vector
-
-from ufl.finiteelement import (FiniteElement, EnrichedElement, VectorElement, MixedElement,
-                               OuterProductElement, TensorElement,
-                               FacetElement, InteriorElement, BrokenElement, TraceElement)
 from ufl.utils.sequences import product
 
+
 def sub_elements_with_mappings(element):
     "Return an ordered list of the largest subelements that have a defined mapping."
     if element.mapping() != "undefined":
@@ -51,6 +49,7 @@ def sub_elements_with_mappings(element):
             elements.extend(sub_elements_with_mappings(subelm))
     return elements
 
+
 def create_nested_lists(shape):
     if len(shape) == 0:
         return [None]
@@ -59,6 +58,7 @@ def create_nested_lists(shape):
     else:
         return [create_nested_lists(shape[1:]) for i in range(shape[0])]
 
+
 def reshape_to_nested_list(components, shape):
     if len(shape) == 0:
         assert len(components) == 1
@@ -70,6 +70,7 @@ def reshape_to_nested_list(components, shape):
         n = product(shape[1:])
         return [reshape_to_nested_list(components[n*i:n*(i+1)], shape[1:]) for i in range(shape[0])]
 
+
 def apply_single_function_pullbacks(g):
     element = g.ufl_element()
     mapping = element.mapping()
@@ -79,7 +80,9 @@ def apply_single_function_pullbacks(g):
     gsh = g.ufl_shape
     rsh = r.ufl_shape
 
-    # Shortcut the "identity" case which includes Expression and Constant from dolfin that may be ill-formed without a domain (until we get that fixed)
+    # Shortcut the "identity" case which includes Expression and
+    # Constant from dolfin that may be ill-formed without a domain
+    # (until we get that fixed)
     if mapping == "identity":
         assert rsh == gsh
         return r
@@ -93,16 +96,13 @@ def apply_single_function_pullbacks(g):
     detJ = JacobianDeterminant(domain)
     Jinv = JacobianInverse(domain)
 
-    tdim = domain.topological_dimension()
-    gdim = domain.geometric_dimension()
-
-    # Create contravariant transform for reuse
-    # (note that detJ is the _signed_ (pseudo-)determinant)
+    # Create contravariant transform for reuse (note that detJ is the
+    # _signed_ (pseudo-)determinant)
     transform_hdiv = (1.0/detJ) * J
 
     # Shortcut simple cases for a more efficient representation,
-    # including directly Piola-mapped elements and mixed elements
-    # of any combination of affinely mapped elements without symmetries
+    # including directly Piola-mapped elements and mixed elements of
+    # any combination of affinely mapped elements without symmetries
     if mapping == "symmetries":
         fcm = element.flattened_sub_element_mapping()
         assert gsize >= rsize
@@ -117,28 +117,39 @@ def apply_single_function_pullbacks(g):
         assert transform_hdiv.ufl_shape == (gsize, rsize)
         i, j = indices(2)
         f = as_vector(transform_hdiv[i, j]*r[j], i)
-        #f = as_tensor(transform_hdiv[i, j]*r[k,j], (k,i)) # FIXME: Handle Vector(Piola) here?
+        # f = as_tensor(transform_hdiv[i, j]*r[k,j], (k,i)) # FIXME: Handle Vector(Piola) here?
         assert f.ufl_shape == g.ufl_shape
         return f
     elif mapping == "covariant Piola":
         assert Jinv.ufl_shape == (rsize, gsize)
         i, j = indices(2)
         f = as_vector(Jinv[j, i]*r[j], i)
-        #f = as_tensor(Jinv[j, i]*r[k,j], (k,i)) # FIXME: Handle Vector(Piola) here?
+        # f = as_tensor(Jinv[j, i]*r[k,j], (k,i)) # FIXME: Handle Vector(Piola) here?
+        assert f.ufl_shape == g.ufl_shape
+        return f
+    elif mapping == "double covariant Piola":
+        i, j, m, n = indices(4)
+        f = as_tensor(Jinv[m, i]*r[m, n]*Jinv[n, j], (i, j))
+        assert f.ufl_shape == g.ufl_shape
+        return f
+    elif mapping == "double contravariant Piola":
+        i, j, m, n = indices(4)
+        f = as_tensor((1.0/detJ)*(1.0/detJ)*J[i, m]*r[m, n]*J[j, n], (i, j))
         assert f.ufl_shape == g.ufl_shape
         return f
 
-
-    # By placing components in a list and using as_vector at the end, we're
-    # assuming below that both global function g and its reference value r
-    # have vector shape, which is the case for most elements with the exceptions:
+    # By placing components in a list and using as_vector at the end,
+    # we're assuming below that both global function g and its
+    # reference value r have vector shape, which is the case for most
+    # elements with the exceptions:
     # - TensorElements
-    #   - All cases with scalar subelements and without symmetries are covered by the shortcut above
+    #   - All cases with scalar subelements and without symmetries
+    #     are covered by the shortcut above
     #     (ONLY IF REFERENCE VALUE SHAPE PRESERVES TENSOR RANK)
-    #   - All cases with scalar subelements and without symmetries are covered by the shortcut above
+    #   - All cases with scalar subelements and without symmetries are
+    #     covered by the shortcut above
     # - VectorElements of vector-valued basic elements (FIXME)
     # - TensorElements with symmetries (FIXME)
-    # - Tensor-valued FiniteElements (the new Regge elements)
     assert len(gsh) == 1
     assert len(rsh) == 1
 
@@ -188,13 +199,40 @@ def apply_single_function_pullbacks(g):
             for i in range(gm):
                 g_components[gpos + i] = Jinv[j, i]*rv[j]
 
+        elif mp == "double covariant Piola":
+            # components are flatten, map accordingly
+            rv = as_vector([r[rpos+k] for k in range(rm)])
+            dim = subelm.value_shape()[0]
+            for i in range(dim):
+                for j in range(dim):
+                    gv = 0
+                    # int times Index is not allowed. so sum by hand
+                    for m in range(dim):
+                        for n in range(dim):
+                            gv += Jinv[m, i]*rv[m*dim+n]*Jinv[n, j]
+                    g_components[gpos + i * dim + j] = gv
+
+        elif mp == "double contravariant Piola":
+            # components are flatten, map accordingly
+            rv = as_vector([r[rpos+k] for k in range(rm)])
+            dim = subelm.value_shape()[0]
+            for i in range(dim):
+                for j in range(dim):
+                    gv = 0
+                    # int times Index is not allowed. so sum by hand
+                    for m in range(dim):
+                        for n in range(dim):
+                            gv += (1.0/detJ)*(1.0/detJ)*J[i, m]*rv[m*dim+n]*J[j, n]
+                    g_components[gpos + i * dim + j] = gv
+
         else:
             error("Unknown subelement mapping type %s for element %s." % (mp, str(subelm)))
 
         gpos += gm
         rpos += rm
 
-    # Wrap up components in a vector, must return same shape as input function g
+    # Wrap up components in a vector, must return same shape as input
+    # function g
     assert len(gsh) == 1
     f = as_vector(g_components)
     assert f.ufl_shape == g.ufl_shape
@@ -212,9 +250,11 @@ class FunctionPullbackApplier(MultiFunction):
 
     @memoized_handler
     def form_argument(self, o):
-        # Represent 0-derivatives of form arguments on reference element
+        # Represent 0-derivatives of form arguments on reference
+        # element
         return apply_single_function_pullbacks(o)
 
+
 def apply_function_pullbacks(expr):
     """Change representation of coefficients and arguments in expression
     by applying Piola mappings where applicable and representing all
diff --git a/ufl/algorithms/apply_geometry_lowering.py b/ufl/algorithms/apply_geometry_lowering.py
index cbd642e..ff4fdfc 100644
--- a/ufl/algorithms/apply_geometry_lowering.py
+++ b/ufl/algorithms/apply_geometry_lowering.py
@@ -5,7 +5,7 @@ This means replacing high-level types with expressions
 of mostly the Jacobian and reference cell data.
 """
 
-# Copyright (C) 2013-2015 Martin Sandve Alnæs
+# Copyright (C) 2013-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -25,25 +25,26 @@ of mostly the Jacobian and reference cell data.
 from six.moves import xrange as range
 
 from ufl.log import error, warning
-from ufl.assertions import ufl_assert
 
 from ufl.core.multiindex import Index, indices
 from ufl.corealg.multifunction import MultiFunction, memoized_handler
 from ufl.corealg.map_dag import map_expr_dag
+from ufl.measure import custom_integral_types, point_integral_types
 
 from ufl.classes import (Expr, Form, Integral,
-                         ReferenceGrad, ReferenceValue,
+                         ReferenceGrad,
                          Jacobian, JacobianInverse, JacobianDeterminant,
                          CellOrientation, CellOrigin, CellCoordinate,
                          FacetJacobian, FacetJacobianDeterminant,
                          CellFacetJacobian,
                          CellEdgeVectors, FacetEdgeVectors,
-                         FacetNormal, CellNormal, ReferenceNormal,
+                         ReferenceNormal,
                          ReferenceCellVolume, ReferenceFacetVolume,
                          CellVolume, FacetArea,
-                         SpatialCoordinate)
-#FacetJacobianInverse,
-#FacetOrientation, QuadratureWeight,
+                         SpatialCoordinate,
+                         FloatValue)
+# FacetJacobianInverse,
+# FacetOrientation, QuadratureWeight,
 
 from ufl.tensors import as_tensor, as_vector
 from ufl.operators import sqrt, max_value, min_value
@@ -71,16 +72,19 @@ class GeometryLoweringApplier(MultiFunction):
         domain = o.ufl_domain()
         if domain.ufl_coordinate_element().mapping() != "identity":
             error("Piola mapped coordinates are not implemented.")
-        # Note: No longer supporting domain.coordinates(), always preserving SpatialCoordinate object.
-        # However if Jacobians are not preserved, using ReferenceGrad(SpatialCoordinate(domain)) to represent them.
+        # Note: No longer supporting domain.coordinates(), always
+        # preserving SpatialCoordinate object.  However if Jacobians
+        # are not preserved, using
+        # ReferenceGrad(SpatialCoordinate(domain)) to represent them.
         x = self.spatial_coordinate(SpatialCoordinate(domain))
         return ReferenceGrad(x)
 
     @memoized_handler
     def _future_jacobian(self, o):
-        # If we're not using Coefficient to represent the spatial coordinate,
-        # we can just as well just return o here too unless we add representation
-        # of basis functions and dofs to the ufl layer (which is nice to avoid).
+        # If we're not using Coefficient to represent the spatial
+        # coordinate, we can just as well just return o here too
+        # unless we add representation of basis functions and dofs to
+        # the ufl layer (which is nice to avoid).
         return o
 
     @memoized_handler
@@ -90,7 +94,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         J = self.jacobian(Jacobian(domain))
-        # TODO: This could in principle use preserve_types[JacobianDeterminant] with minor refactoring:
+        # TODO: This could in principle use
+        # preserve_types[JacobianDeterminant] with minor refactoring:
         K = inverse_expr(J)
         return K
 
@@ -103,8 +108,9 @@ class GeometryLoweringApplier(MultiFunction):
         J = self.jacobian(Jacobian(domain))
         detJ = determinant_expr(J)
 
-        # TODO: Is "signing" the determinant for manifolds the cleanest approach?
-        #       The alternative is to have a specific type for the unsigned pseudo-determinant.
+        # TODO: Is "signing" the determinant for manifolds the
+        #       cleanest approach?  The alternative is to have a
+        #       specific type for the unsigned pseudo-determinant.
         if domain.topological_dimension() < domain.geometric_dimension():
             co = CellOrientation(domain)
             detJ = co*detJ
@@ -138,14 +144,16 @@ class GeometryLoweringApplier(MultiFunction):
             return o
 
         domain = o.ufl_domain()
+        #tdim = domain.topological_dimension()
         FJ = self.facet_jacobian(FacetJacobian(domain))
         detFJ = determinant_expr(FJ)
 
-        # TODO: Should we "sign" the facet jacobian determinant for manifolds?
-        #       It's currently used unsigned in apply_integral_scaling.
-        #if domain.topological_dimension() < domain.geometric_dimension():
-        #    co = CellOrientation(domain)
-        #    detFJ = co*detFJ
+        # TODO: Should we "sign" the facet jacobian determinant for
+        #       manifolds?  It's currently used unsigned in
+        #       apply_integral_scaling.
+        # if domain.topological_dimension() < domain.geometric_dimension():
+        #     co = CellOrientation(domain)
+        #     detFJ = co*detFJ
 
         return detFJ
 
@@ -156,7 +164,8 @@ class GeometryLoweringApplier(MultiFunction):
             return o
         if o.ufl_domain().ufl_coordinate_element().mapping() != "identity":
             error("Piola mapped coordinates are not implemented.")
-        # No longer supporting domain.coordinates(), always preserving SpatialCoordinate object.
+        # No longer supporting domain.coordinates(), always preserving
+        # SpatialCoordinate object.
         return o
 
     @memoized_handler
@@ -188,7 +197,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the cell volume of an affine cell.")
             return o
 
@@ -202,11 +212,17 @@ class GeometryLoweringApplier(MultiFunction):
             return o
 
         domain = o.ufl_domain()
+        tdim = domain.topological_dimension()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the facet area of an affine cell.")
             return o
 
+        # Area of "facet" of interval (i.e. "area" of a vertex) is defined as 1.0
+        if tdim == 1:
+            return FloatValue(1.0)
+
         r = self.facet_jacobian_determinant(FacetJacobianDeterminant(domain))
         r0 = ReferenceFacetVolume(domain)
         return abs(r * r0)
@@ -218,7 +234,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the circumradius of an affine cell.")
             return o
 
@@ -271,7 +288,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the min_cell_edge_length of an affine cell.")
             return o
 
@@ -300,7 +318,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the max_cell_edge_length of an affine cell.")
             return o
 
@@ -329,7 +348,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the min_facet_edge_length of an affine cell.")
             return o
 
@@ -355,7 +375,8 @@ class GeometryLoweringApplier(MultiFunction):
 
         domain = o.ufl_domain()
         if not domain.is_piecewise_linear_simplex_domain():
-            # Don't lower for non-affine cells, instead leave it to form compiler
+            # Don't lower for non-affine cells, instead leave it to
+            # form compiler
             warning("Only know how to compute the max_facet_edge_length of an affine cell.")
             return o
 
@@ -383,7 +404,7 @@ class GeometryLoweringApplier(MultiFunction):
         gdim = domain.geometric_dimension()
         tdim = domain.topological_dimension()
 
-        if tdim == gdim - 1: # n-manifold embedded in n-1 space
+        if tdim == gdim - 1:  # n-manifold embedded in n-1 space
             i = Index()
             J = self.jacobian(Jacobian(domain))
 
@@ -393,12 +414,14 @@ class GeometryLoweringApplier(MultiFunction):
                 t1 = as_vector(J[i, 1], i)
                 cell_normal = cross_expr(t0, t1)
             elif tdim == 1:
-                # Line in 2D (cell normal is 'up' for a line pointing to the 'right')
+                # Line in 2D (cell normal is 'up' for a line pointing
+                # to the 'right')
                 cell_normal = as_vector((-J[1, 0], J[0, 0]))
             else:
                 error("Cell normal not implemented for tdim %d, gdim %d" % (tdim, gdim))
 
-            # Return normalized vector, sign corrected by cell orientation
+            # Return normalized vector, sign corrected by cell
+            # orientation
             co = CellOrientation(domain)
             return co * cell_normal / sqrt(cell_normal[i]*cell_normal[i])
         else:
@@ -413,9 +436,9 @@ class GeometryLoweringApplier(MultiFunction):
         tdim = domain.topological_dimension()
 
         if tdim == 1:
-            # Special-case 1D (possibly immersed), for which we say that
-            # n is just in the direction of J.
-            J = self.jacobian(Jacobian(domain)) # dx/dX
+            # Special-case 1D (possibly immersed), for which we say
+            # that n is just in the direction of J.
+            J = self.jacobian(Jacobian(domain))  # dx/dX
             ndir = J[:, 0]
 
             gdim = domain.geometric_dimension()
@@ -429,9 +452,10 @@ class GeometryLoweringApplier(MultiFunction):
             n = rn[0] * ndir / nlen
             r = n
         else:
-            # Recall that the covariant Piola transform u -> J^(-T)*u preserves
-            # tangential components. The normal vector is characterised by
-            # having zero tangential component in reference and physical space.
+            # Recall that the covariant Piola transform u -> J^(-T)*u
+            # preserves tangential components. The normal vector is
+            # characterised by having zero tangential component in
+            # reference and physical space.
             Jinv = self.jacobian_inverse(JacobianInverse(domain))
             i, j = indices(2)
 
@@ -444,10 +468,11 @@ class GeometryLoweringApplier(MultiFunction):
             n = ndir / sqrt(ndir[i]*ndir[i])
             r = n
 
-        ufl_assert(r.ufl_shape == o.ufl_shape,
-                   "Inconsistent dimensions (in=%d, out=%d)." % (o.ufl_shape[0], r.ufl_shape[0]))
+        if r.ufl_shape != o.ufl_shape:
+            error("Inconsistent dimensions (in=%d, out=%d)." % (o.ufl_shape[0], r.ufl_shape[0]))
         return r
 
+
 def apply_geometry_lowering(form, preserve_types=()):
     """Change GeometricQuantity objects in expression to the lowest level GeometricQuantity objects.
 
@@ -463,7 +488,7 @@ def apply_geometry_lowering(form, preserve_types=()):
 
     elif isinstance(form, Integral):
         integral = form
-        if integral.integral_type() in ("custom", "vertex"):
+        if integral.integral_type() in (custom_integral_types + point_integral_types):
             automatic_preserve_types = [SpatialCoordinate, Jacobian]
         else:
             automatic_preserve_types = [CellCoordinate]
diff --git a/ufl/algorithms/apply_integral_scaling.py b/ufl/algorithms/apply_integral_scaling.py
index f36b02e..84aa55a 100644
--- a/ufl/algorithms/apply_integral_scaling.py
+++ b/ufl/algorithms/apply_integral_scaling.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithm for replacing gradients in an expression with reference gradients and coordinate mappings."""
 
-# Copyright (C) 2013-2015 Martin Sandve Alnæs
+# Copyright (C) 2013-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,12 +18,9 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
-from six.moves import xrange as range
-
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
-
+from ufl.log import error
 from ufl.classes import JacobianDeterminant, FacetJacobianDeterminant, QuadratureWeight, Form, Integral
+from ufl.measure import custom_integral_types, point_integral_types
 
 
 def compute_integrand_scaling_factor(integral):
@@ -31,17 +28,18 @@ def compute_integrand_scaling_factor(integral):
 
     domain = integral.ufl_domain()
     integral_type = integral.integral_type()
-    #co = CellOrientation(domain)
+    # co = CellOrientation(domain)
     weight = QuadratureWeight(domain)
     tdim = domain.topological_dimension()
-    #gdim = domain.geometric_dimension()
+    # gdim = domain.geometric_dimension()
 
     if integral_type == "cell":
         scale = abs(JacobianDeterminant(domain)) * weight
 
     elif integral_type.startswith("exterior_facet"):
         if tdim > 1:
-            # Scaling integral by facet jacobian determinant and quadrature weight
+            # Scaling integral by facet jacobian determinant and
+            # quadrature weight
             scale = FacetJacobianDeterminant(domain) * weight
         else:
             # No need to scale 'integral' over a vertex
@@ -49,17 +47,19 @@ def compute_integrand_scaling_factor(integral):
 
     elif integral_type.startswith("interior_facet"):
         if tdim > 1:
-            # Scaling integral by facet jacobian determinant from one side and quadrature weight
+            # Scaling integral by facet jacobian determinant from one
+            # side and quadrature weight
             scale = FacetJacobianDeterminant(domain)('+') * weight
         else:
             # No need to scale 'integral' over a vertex
             scale = 1
 
-    elif integral_type in ("custom", "interface", "overlap", "cutcell"):
-        # Scaling with custom weight, which includes eventual volume scaling
+    elif integral_type in custom_integral_types:
+        # Scaling with custom weight, which includes eventual volume
+        # scaling
         scale = weight
 
-    elif integral_type in ("vertex", "point"):
+    elif integral_type in point_integral_types:
         # No need to scale 'integral' over a point
         scale = 1
 
diff --git a/ufl/algorithms/apply_restrictions.py b/ufl/algorithms/apply_restrictions.py
index 34c02c5..a7473d7 100644
--- a/ufl/algorithms/apply_restrictions.py
+++ b/ufl/algorithms/apply_restrictions.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module contains the apply_restrictions algorithm which propagates restrictions in a form towards the terminals."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,33 +19,32 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 
-from ufl.assertions import ufl_assert
 from ufl.log import error
-
-from ufl.core.terminal import Terminal
-from ufl.classes import Coefficient, Argument, GeometricQuantity, Restricted
+from ufl.classes import Restricted
 from ufl.corealg.multifunction import MultiFunction
 from ufl.corealg.map_dag import map_expr_dag
 from ufl.algorithms.map_integrands import map_integrand_dags
 from ufl.measure import integral_type_to_measure_name
 
+
 class RestrictionPropagator(MultiFunction):
     def __init__(self, side=None):
         MultiFunction.__init__(self)
         self.current_restriction = side
         self.default_restriction = "+"
         if self.current_restriction is None:
-            self._rp = {
-                "+": RestrictionPropagator("+"),
-                "-": RestrictionPropagator("-")
-                }
+            self._rp = {"+": RestrictionPropagator("+"),
+                        "-": RestrictionPropagator("-")}
 
     def restricted(self, o):
         "When hitting a restricted quantity, visit child with a separate restriction algorithm."
-        # Assure that we have only two levels here, inside or outside the Restricted node
-        ufl_assert(self.current_restriction is None, "Cannot restrict an expression twice.")
+        # Assure that we have only two levels here, inside or outside
+        # the Restricted node
+        if self.current_restriction is not None:
+            error("Cannot restrict an expression twice.")
         # Configure a propagator for this side and apply to subtree
-        return map_expr_dag(self._rp[o.side()], o.ufl_operands[0]) # FIXME: Reuse cache between these calls!
+        # FIXME: Reuse cache between these calls!
+        return map_expr_dag(self._rp[o.side()], o.ufl_operands[0])
 
     # --- Reusable rules
 
@@ -55,7 +54,8 @@ class RestrictionPropagator(MultiFunction):
 
     def _require_restriction(self, o):
         "Restrict a discontinuous quantity to current side, require a side to be set."
-        ufl_assert(self.current_restriction is not None, "Discontinuous type %s must be restricted." % o._ufl_class_.__name__)
+        if self.current_restriction is None:
+            error("Discontinuous type %s must be restricted." % o._ufl_class_.__name__)
         return o(self.current_restriction)
 
     def _default_restricted(self, o):
@@ -77,19 +77,22 @@ class RestrictionPropagator(MultiFunction):
     def _missing_rule(self, o):
         error("Missing rule for %s" % o._ufl_class_.__name__)
 
-
     # --- Rules for operators
 
     # Default: Operators should reconstruct only if subtrees are not touched
     operator = MultiFunction.reuse_if_untouched
 
-    # Assuming apply_derivatives has been called, propagating Grad inside the Restricted nodes.
-    grad = _require_restriction # Considering all grads to be discontinuous, may need something else for facet functions in future
+    # Assuming apply_derivatives has been called,
+    # propagating Grad inside the Restricted nodes.
+    # Considering all grads to be discontinuous, may
+    # want something else for facet functions in future.
+    grad = _require_restriction
+
     # Assuming averages are also applied directly to the terminal or grad nodes
     cell_avg = _require_restriction
     facet_avg = _ignore_restriction
 
-    def variable(self, o, op):
+    def variable(self, o, op, label):
         "Strip variable."
         return op
 
@@ -106,13 +109,32 @@ class RestrictionPropagator(MultiFunction):
 
     # --- Rules for terminals
 
+    # Require handlers to be specified for all terminals
+    terminal = _missing_rule
+
+    multi_index = _ignore_restriction
+    label = _ignore_restriction
+
     # Default: Literals should ignore restriction
-    terminal = _ignore_restriction # TODO: Require handlers to be specified for all terminals? That would be safer.
+    constant_value = _ignore_restriction
 
     # Even arguments with continuous elements such as Lagrange must be
-    # restricted to associate with the right part of the element matrix
+    # restricted to associate with the right part of the element
+    # matrix
     argument = _require_restriction
 
+    # Defaults for geometric quantities
+    geometric_cell_quantity = _require_restriction
+    geometric_facet_quantity = _require_restriction
+
+    # Only a few geometric quantities are independent on the restriction:
+    facet_coordinate = _ignore_restriction
+    quadrature_weight = _ignore_restriction
+
+    # Assuming homogeoneous mesh
+    reference_cell_volume = _ignore_restriction
+    reference_facet_volume = _ignore_restriction
+
     def coefficient(self, o):
         "Allow coefficients to be unrestricted (apply default if so) if the values are fully continuous across the facet."
         e = o.ufl_element()
@@ -121,7 +143,7 @@ class RestrictionPropagator(MultiFunction):
         # TODO: Move this choice to the element class?
         if (f == "Lagrange" and d > 0) or f == "Real":
             # If the coefficient _value_ is _fully_ continuous
-            return self._default_restricted(o) # Must still be computed from one of the sides, we just don't care which
+            return self._default_restricted(o)  # Must still be computed from one of the sides, we just don't care which
         else:
             return self._require_restriction(o)
 
@@ -134,68 +156,84 @@ class RestrictionPropagator(MultiFunction):
         td = D.topological_dimension()
 
         if f == "Lagrange" and d == 1 and gd == td:
-            # For meshes with a continuous linear non-manifold coordinate field,
-            # the facet normal from side - points in the opposite direction of the one from side +.
-            # We must still require a side to be chosen by the user but rewrite n- -> n+.
-            # This is an optimization, possibly premature, however it's more difficult to do at a later stage.
+            # For meshes with a continuous linear non-manifold
+            # coordinate field, the facet normal from side - points in
+            # the opposite direction of the one from side +.  We must
+            # still require a side to be chosen by the user but
+            # rewrite n- -> n+.  This is an optimization, possibly
+            # premature, however it's more difficult to do at a later
+            # stage.
             return self._opposite(o)
         else:
-            # For other meshes, we require a side to be chosen by the user and respect that
+            # For other meshes, we require a side to be
+            # chosen by the user and respect that
             return self._require_restriction(o)
 
-    # Although the physical normal can be flipped when moving from
-    # + to - in some circumstances, the reference normal cannot.
-    reference_normal = _require_restriction
-
-    # Defaults for geometric quantities
-    geometric_cell_quantity = _missing_rule  #_require_restriction
-    geometric_facet_quantity = _missing_rule #_ignore_restriction
-
-    spatial_coordinate = _default_restricted # Continuous but computed from cell data
-    cell_coordinate = _require_restriction   # Depends on cell
-    facet_coordinate = _ignore_restriction   # Independent of cell
-
-    cell_origin = _require_restriction       # Depends on cell
-    facet_origin = _default_restricted       # Depends on cell but only to get to the facet # TODO: Is this valid for quads?
-    cell_facet_origin = _require_restriction # Depends on cell
 
-    jacobian = _require_restriction             # Property of cell
-    jacobian_determinant = _require_restriction # ...
-    jacobian_inverse = _require_restriction     # ...
-
-    facet_jacobian = _default_restricted              # Depends on cell only to get to the facet
-    facet_jacobian_determinant = _default_restricted  # ... (actually continuous?)
-    facet_jacobian_inverse = _default_restricted      # ...
+def apply_restrictions(expression):
+    "Propagate restriction nodes to wrap differential terminals directly."
+    integral_types = [k for k in integral_type_to_measure_name.keys()
+                      if k.startswith("interior_facet")]
+    rules = RestrictionPropagator()
+    return map_integrand_dags(rules, expression,
+                              only_integral_type=integral_types)
 
-    cell_facet_jacobian = _require_restriction             # Depends on cell
-    cell_facet_jacobian_determinant = _require_restriction # ...
-    cell_facet_jacobian_inverse = _require_restriction     # ...
-    cell_edge_vectors = _require_restriction               # ...
 
-    cell_normal = _require_restriction  # Property of cell
+class DefaultRestrictionApplier(MultiFunction):
+    def __init__(self, side=None):
+        MultiFunction.__init__(self)
+        self.current_restriction = side
+        self.default_restriction = "+"
+        if self.current_restriction is None:
+            self._rp = {"+": DefaultRestrictionApplier("+"),
+                        "-": DefaultRestrictionApplier("-")}
 
-    #facet_tangents = _default_restricted # Independent of cell
-    #cell_tangents = _require_restriction # Depends on cell
-    #cell_midpoint = _require_restriction # Depends on cell
-    #facet_midpoint = _default_restricted # Depends on cell only to get to the facet
+    def terminal(self, o):
+        # Most terminals are unchanged
+        return o
 
-    cell_volume = _require_restriction        # Property of cell
-    circumradius = _require_restriction       # Property of cell
-    #cell_surface_area = _require_restriction # Property of cell
+    # Default: Operators should reconstruct only if subtrees are not touched
+    operator = MultiFunction.reuse_if_untouched
 
-    facet_area = _default_restricted            # Depends on cell only to get to the facet
-    #facet_diameter = _default_restricted       # Depends on cell only to get to the facet
-    min_facet_edge_length = _default_restricted # Depends on cell only to get to the facet
-    max_facet_edge_length = _default_restricted # Depends on cell only to get to the facet
+    def restricted(self, o):
+        # Don't restrict twice
+        return o
 
-    cell_orientation = _require_restriction # Property of cell
-    facet_orientation = _require_restriction # Property of cell (depends on local facet number in cell)
-    quadrature_weight = _ignore_restriction # Independent of cell
+    def derivative(self, o):
+        # I don't think it's safe to just apply default restriction
+        # to the argument of any derivative, i.e. grad(cg1_function)
+        # is not continuous across cells even if cg1_function is.
+        return o
 
+    def _default_restricted(self, o):
+        "Restrict a continuous quantity to default side if no current restriction is set."
+        r = self.current_restriction
+        if r is None:
+            r = self.default_restriction
+        return o(r)
 
-def apply_restrictions(expression):
-    "Propagate restriction nodes to wrap differential terminals directly."
+    # These are the same from either side but to compute them
+    # cell (or facet) data from one side must be selected:
+    spatial_coordinate = _default_restricted
+    # Depends on cell only to get to the facet:
+    facet_jacobian = _default_restricted
+    facet_jacobian_determinant = _default_restricted
+    facet_jacobian_inverse = _default_restricted
+    # facet_tangents = _default_restricted
+    # facet_midpoint = _default_restricted
+    facet_area = _default_restricted
+    # facet_diameter = _default_restricted
+    min_facet_edge_length = _default_restricted
+    max_facet_edge_length = _default_restricted
+    facet_origin = _default_restricted  # FIXME: Is this valid for quads?
+
+
+def apply_default_restrictions(expression):
+    """Some terminals can be restricted from either side.
+
+    This applies a default restriction to such terminals if unrestricted."""
     integral_types = [k for k in integral_type_to_measure_name.keys()
                       if k.startswith("interior_facet")]
-    rules = RestrictionPropagator()
-    return map_integrand_dags(rules, expression, only_integral_type=integral_types)
+    rules = DefaultRestrictionApplier()
+    return map_integrand_dags(rules, expression,
+                              only_integral_type=integral_types)
diff --git a/ufl/algorithms/argument_dependencies.py b/ufl/algorithms/argument_dependencies.py
deleted file mode 100644
index ee1ffce..0000000
--- a/ufl/algorithms/argument_dependencies.py
+++ /dev/null
@@ -1,175 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Algorithms for analysing argument dependencies in expressions."""
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-#
-# Modified by Anders Logg, 2009-2010
-#
-# First added:  2008-05-07
-# Last changed: 2012-04-12
-
-from ufl.assertions import ufl_assert
-from ufl.classes import Expr
-from ufl.algorithms.transformer import Transformer
-
-
-class NotMultiLinearException(Exception):
-    def __init__(self, *args, **kwargs):
-        Exception.__init__(self, *args, **kwargs)
-
-class ArgumentDependencyExtracter(Transformer):
-    def __init__(self):
-        Transformer.__init__(self)
-        self._empty = frozenset()
-
-    def operator(self, o, *opdeps):
-        "Default for Operators: nonlinear in all operands."
-        for d in opdeps:
-            if d:
-                raise NotMultiLinearException(repr(o))
-        return self._empty
-
-    def terminal(self, o):
-        "Default for terminals: no dependency on Arguments."
-        return self._empty
-
-    def variable(self, o):
-        # Check variable cache to reuse previously transformed variable if possible
-        e, l = o.ufl_operands
-        d = self._variable_cache.get(l)
-        if d is None:
-            # Visit the expression our variable represents
-            d = self.visit(e)
-            self._variable_cache[l] = d
-        return d
-
-    def argument(self, o):
-        d = frozenset((o,))
-        return frozenset((d,))
-
-    def linear(self, o, a):
-        "Nonterminals that are linear with a single argument."
-        return a
-    nabla_grad = linear
-    nabla_div = linear
-    grad = linear
-    div = linear
-    curl = linear
-    reference_grad = linear
-    reference_div = linear
-    reference_curl = linear
-    transposed = linear
-    trace = linear
-    skew = linear
-    sym = linear
-    positive_restricted = linear
-    negative_restricted = linear
-    cell_avg = linear
-    facet_avg = linear
-
-    def indexed(self, o, f, i):
-        return f
-
-    def spatial_derivative(self, o, a, b):
-        return a
-
-    def variable_derivative(self, o, a, b):
-        if b:
-            raise NotMultiLinearException(repr(o))
-        return a
-
-    def component_tensor(self, o, f, i):
-        return f
-
-    def list_tensor(self, o, *opdeps):
-        "Require same dependencies for all listtensor entries."
-        d = opdeps[0]
-        for d2 in opdeps[1:]:
-            if not d == d2:
-                raise NotMultiLinearException(repr(o))
-        return d
-
-    def conditional(self, o, cond, t, f):
-        "Considering EQ, NE, LE, GE, LT, GT nonlinear in this context."
-        if cond or (not t == f):
-            raise NotMultiLinearException(repr(o))
-        return t
-
-    def min_value(self, o, l, r):
-        "Considering min, max nonlinear in this context."
-        if l or r:
-            raise NotMultiLinearException(repr(o))
-        return t
-    max_value = min_value
-
-    def division(self, o, a, b):
-        "Arguments cannot be in the denominator."
-        if b:
-            raise NotMultiLinearException(repr(o))
-        return a
-
-    def index_sum(self, o, f, i):
-        "Index sums inherit the dependencies of their summand."
-        return f
-
-    def sum(self, o, *opdeps):
-        """Sums can contain both linear and bilinear terms (we could change
-        this to require that all operands have the same dependencies)."""
-        # convert frozenset to a mutable set
-        deps = set(opdeps[0])
-        for d in opdeps[1:]:
-            # d is a frozenset of frozensets
-            deps.update(d)
-        return frozenset(deps)
-
-    def product(self, o, *opdeps):
-        # Product operands should not depend on the same Arguments
-        c = []
-        adeps, bdeps = opdeps # TODO: Generalize to any number of operands using permutations
-        # for each frozenset ad in the frozenset adeps
-        ufl_assert(isinstance(adeps, frozenset), "Type error")
-        ufl_assert(isinstance(bdeps, frozenset), "Type error")
-        ufl_assert(all(isinstance(ad, frozenset) for ad in adeps), "Type error")
-        ufl_assert(all(isinstance(bd, frozenset) for bd in bdeps), "Type error")
-        none = frozenset((None,))
-        noneset = frozenset((none,))
-        if not adeps:
-            adeps = noneset
-        if not bdeps:
-            bdeps = noneset
-        for ad in adeps:
-            # for each frozenset bd in the frozenset bdeps
-            for bd in bdeps:
-                # build frozenset cd with the combined Argument dependencies from ad and bd
-                cd = (ad | bd) - none
-                # build frozenset cd with the combined Argument dependencies from ad and bd
-                if not len(cd) == len(ad - none) + len(bd - none):
-                    raise NotMultiLinearException(repr(o))
-                # remember this dependency combination
-                if cd:
-                    c.append(cd)
-        return frozenset(c)
-    inner = product
-    outer = product
-    dot = product
-    cross = product
-
-def extract_argument_dependencies(e):
-    "Extract a set of sets of Arguments."
-    ufl_assert(isinstance(e, Expr), "Expecting an Expr.")
-    return ArgumentDependencyExtracter().visit(e)
diff --git a/ufl/algorithms/change_to_reference.py b/ufl/algorithms/change_to_reference.py
index 055e6ff..e880988 100644
--- a/ufl/algorithms/change_to_reference.py
+++ b/ufl/algorithms/change_to_reference.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithm for replacing gradients in an expression with reference gradients and coordinate mappings."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,37 +20,28 @@
 
 from six.moves import xrange as range
 
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
+from ufl.log import error
 
-from ufl.core.multiindex import Index, indices
-from ufl.corealg.multifunction import MultiFunction, memoized_handler
+from ufl.core.multiindex import indices
+from ufl.corealg.multifunction import MultiFunction
 from ufl.corealg.map_dag import map_expr_dag
 
-from ufl.classes import (Expr, FormArgument, GeometricQuantity,
+from ufl.classes import (FormArgument, GeometricQuantity,
                          Terminal, ReferenceGrad, Grad, Restricted, ReferenceValue,
                          Jacobian, JacobianInverse, JacobianDeterminant,
-                         FacetJacobian, FacetJacobianInverse, FacetJacobianDeterminant,
-                         CellFacetJacobian,
-                         CellEdgeVectors, FacetEdgeVectors,
-                         FacetNormal, CellNormal, ReferenceNormal,
-                         CellVolume, FacetArea,
-                         CellOrientation, FacetOrientation, QuadratureWeight,
-                         SpatialCoordinate, Indexed, MultiIndex, FixedIndex)
-
-from ufl.constantvalue import as_ufl, Identity
-from ufl.tensoralgebra import Transposed
-from ufl.tensors import as_tensor, as_vector, as_scalar, ComponentTensor
-from ufl.operators import sqrt, max_value, min_value, sign
+                         Indexed, MultiIndex, FixedIndex)
+
+from ufl.constantvalue import as_ufl
+from ufl.tensors import as_tensor
 from ufl.permutation import compute_indices
 
-from ufl.compound_expressions import determinant_expr, cross_expr, inverse_expr
-from ufl.finiteelement import FiniteElement, EnrichedElement, VectorElement, MixedElement, OuterProductElement, TensorElement, FacetElement, InteriorElement, BrokenElement, TraceElement
+from ufl.finiteelement import MixedElement
 
 from ufl.algorithms.apply_function_pullbacks import apply_function_pullbacks
 from ufl.algorithms.apply_geometry_lowering import apply_geometry_lowering
 from ufl.checks import is_cellwise_constant
 
+
 """
 # Some notes:
 # Below, let v_i mean physical coordinate of vertex i and V_i mean the reference cell coordinate of the same vertex.
@@ -159,7 +150,8 @@ class NEWChangeToReferenceGrad(MultiFunction):
 
     def restricted(self, o, *dummy_ops):
         "Store modifier state."
-        ufl_assert(self._restricted == '', "Not expecting nested restrictions.")
+        if self._restricted != '':
+            error("Not expecting nested restrictions.")
         self._restricted = o.side()
         f, = o.ufl_operands
         r = self(f)
@@ -175,7 +167,8 @@ class NEWChangeToReferenceGrad(MultiFunction):
         return r
 
     def facet_avg(self, o, *dummy_ops):
-        ufl_assert(self._avg == '', "Not expecting nested averages.")
+        if self._avg != '':
+            error("Not expecting nested averages.")
         self._avg = "facet"
         f, = o.ufl_operands
         r = self(f)
@@ -183,7 +176,8 @@ class NEWChangeToReferenceGrad(MultiFunction):
         return r
 
     def cell_avg(self, o, *dummy_ops):
-        ufl_assert(self._avg == '', "Not expecting nested averages.")
+        if self._avg != '':
+            error("Not expecting nested averages.")
         self._avg = "cell"
         f, = o.ufl_operands
         r = self(f)
@@ -201,13 +195,15 @@ class NEWChangeToReferenceGrad(MultiFunction):
 
     def _mapped(self, t):
         # Check that we have a valid input object
-        ufl_assert(isinstance(t, Terminal), "Expecting a Terminal.")
+        if not isinstance(t, Terminal):
+            error("Expecting a Terminal.")
 
         # Get modifiers accumulated by previous handler calls
         ngrads = self._ngrads
         restricted = self._restricted
         avg = self._avg
-        ufl_assert(avg == "", "Averaging not implemented.") # FIXME
+        if avg != "":
+            error("Averaging not implemented.")  # FIXME
 
         # These are the global (g) and reference (r) values
         if isinstance(t, FormArgument):
@@ -236,9 +232,9 @@ class NEWChangeToReferenceGrad(MultiFunction):
 
         # Get component indices of global and reference terminal objects
         gtsh = g.ufl_shape
-        rtsh = r.ufl_shape
+        # rtsh = r.ufl_shape
         gtcomponents = compute_indices(gtsh)
-        rtcomponents = compute_indices(rtsh)
+        # rtcomponents = compute_indices(rtsh)
 
         # Create core modified terminal, with eventual
         # layers of grad applied directly to the terminal,
@@ -250,17 +246,19 @@ class NEWChangeToReferenceGrad(MultiFunction):
             g = g(restricted)
             r = r(restricted)
 
-        # Get component indices of global and reference objects with grads applied
+        # Get component indices of global and reference objects with
+        # grads applied
         gsh = g.ufl_shape
-        rsh = r.ufl_shape
-        gcomponents = compute_indices(gsh)
-        rcomponents = compute_indices(rsh)
+        # rsh = r.ufl_shape
+        # gcomponents = compute_indices(gsh)
+        # rcomponents = compute_indices(rsh)
 
         # Get derivative component indices
         dsh = gsh[len(gtsh):]
         dcomponents = compute_indices(dsh)
 
-        # Create nested array to hold expressions for global components mapped from reference values
+        # Create nested array to hold expressions for global
+        # components mapped from reference values
         def ndarray(shape):
             if len(shape) == 0:
                 return [None]
@@ -276,24 +274,26 @@ class NEWChangeToReferenceGrad(MultiFunction):
             if isinstance(t, FormArgument):
 
                 # Find basic subelement and element-local component
-                #ec, element, eoffset = t.ufl_element().extract_component2(gtc) # FIXME: Translate this correctly
+                # ec, element, eoffset = t.ufl_element().extract_component2(gtc) # FIXME: Translate this correctly
                 eoffset = 0
                 ec, element = t.ufl_element().extract_reference_component(gtc)
 
-                # Select mapping M from element, pick row emapping = M[ec,:], or emapping = [] if no mapping
-                ufl_assert(not isinstance(element, MixedElement),
-                           "Expecting a basic element here.")
+                # Select mapping M from element, pick row emapping =
+                # M[ec,:], or emapping = [] if no mapping
+                if isinstance(element, MixedElement):
+                    error("Expecting a basic element here.")
                 mapping = element.mapping()
-                if mapping == "contravariant Piola": #S == HDiv:
-                    # Handle HDiv elements with contravariant piola mapping
-                    # contravariant_hdiv_mapping = (1/det J) * J * PullbackOf(o)
+                if mapping == "contravariant Piola":  # S == HDiv:
+                    # Handle HDiv elements with contravariant piola
+                    # mapping contravariant_hdiv_mapping = (1/det J) *
+                    # J * PullbackOf(o)
                     ec, = ec
-                    emapping = Mdiv[ec,:]
-                elif mapping == "covariant Piola": #S == HCurl:
+                    emapping = Mdiv[ec, :]
+                elif mapping == "covariant Piola":  # S == HCurl:
                     # Handle HCurl elements with covariant piola mapping
                     # covariant_hcurl_mapping = JinvT * PullbackOf(o)
                     ec, = ec
-                    emapping = K[:,ec] # Column of K is row of K.T
+                    emapping = K[:, ec]  # Column of K is row of K.T
                 elif mapping == "identity":
                     emapping = None
                 else:
@@ -307,44 +307,48 @@ class NEWChangeToReferenceGrad(MultiFunction):
                 error("Unexpected type {0}.".format(type(t).__name__))
 
             # Create indices
-            #if rtsh:
-            #    i = Index()
-            ufl_assert(len(dsh) == ngrads, "Mismatch between derivative shape and ngrads.")
+            # if rtsh:
+            #     i = Index()
+            if len(dsh) != ngrads:
+                error("Mismatch between derivative shape and ngrads.")
             if ngrads:
                 ii = indices(ngrads)
             else:
                 ii = ()
 
             # Apply mapping row to reference object
-            if emapping: # Mapped, always nonscalar terminal
-                # Not using IndexSum for the mapping row dot product to keep it simple,
-                # because we don't have a slice type
+            if emapping:  # Mapped, always nonscalar terminal Not
+                # using IndexSum for the mapping row dot product to
+                # keep it simple, because we don't have a slice type
                 emapped_ops = [emapping[s] * Indexed(r, MultiIndex((FixedIndex(eoffset + s),) + ii))
                                for s in range(len(emapping))]
                 emapped = sum(emapped_ops[1:], emapped_ops[0])
-            elif gtc: # Nonscalar terminal, unmapped
+            elif gtc:  # Nonscalar terminal, unmapped
                 emapped = Indexed(r, MultiIndex((FixedIndex(eoffset),) + ii))
-            elif ngrads: # Scalar terminal, unmapped, with derivatives
+            elif ngrads:  # Scalar terminal, unmapped, with derivatives
                 emapped = Indexed(r, MultiIndex(ii))
-            else: # Scalar terminal, unmapped, no derivatives
+            else:  # Scalar terminal, unmapped, no derivatives
                 emapped = r
 
             for di in dcomponents:
-                # Multiply derivative mapping rows, parameterized by free column indices
+                # Multiply derivative mapping rows, parameterized by
+                # free column indices
                 dmapping = as_ufl(1)
                 for j in range(ngrads):
-                    dmapping *= K[ii[j], di[j]] # Row of K is column of JinvT
+                    dmapping *= K[ii[j], di[j]]  # Row of K is column of JinvT
 
-                # Compute mapping from reference values for this particular global component
+                # Compute mapping from reference values for this
+                # particular global component
                 global_value = dmapping * emapped
 
                 # Apply index sums
-                #if rtsh:
-                #    global_value = IndexSum(global_value, MultiIndex((i,)))
-                #for j in range(ngrads): # Applied implicitly in the dmapping * emapped above
-                #    global_value = IndexSum(global_value, MultiIndex((ii[j],)))
+                # if rtsh:
+                #     global_value = IndexSum(global_value, MultiIndex((i,)))
+                # for j in range(ngrads): # Applied implicitly in the dmapping * emapped above
+                #     global_value = IndexSum(global_value, MultiIndex((ii[j],)))
 
-                # This is the component index into the full object with grads applied
+                # This is the component index into the full object
+                # with grads applied
                 gc = gtc + di
 
                 # Insert in nested list
@@ -353,7 +357,8 @@ class NEWChangeToReferenceGrad(MultiFunction):
                     comp = comp[i]
                 comp[0 if gc == () else gc[-1]] = global_value
 
-        # Wrap nested list in as_tensor unless we have a scalar expression
+        # Wrap nested list in as_tensor unless we have a scalar
+        # expression
         if gsh:
             tensor = as_tensor(global_components)
         else:
@@ -371,7 +376,8 @@ class OLDChangeToReferenceGrad(MultiFunction):
         return o
 
     def grad(self, o):
-        # Peel off the Grads and count them, and get restriction if it's between the grad and the terminal
+        # Peel off the Grads and count them, and get restriction if
+        # it's between the grad and the terminal
         ngrads = 0
         restricted = ''
         rv = False
@@ -396,13 +402,14 @@ class OLDChangeToReferenceGrad(MultiFunction):
         Jinv = JacobianInverse(domain)
 
         if is_cellwise_constant(Jinv):
-            # Optimise slightly by turning Grad(Grad(...)) into J^(-T)J^(-T)RefGrad(RefGrad(...))
+            # Optimise slightly by turning Grad(Grad(...)) into
+            # J^(-T)J^(-T)RefGrad(RefGrad(...))
             # rather than J^(-T)RefGrad(J^(-T)RefGrad(...))
 
             # Create some new indices
-            ii = indices(len(f.ufl_shape)) # Indices to get to the scalar component of f
-            jj = indices(ngrads)   # Indices to sum over the local gradient axes with the inverse Jacobian
-            kk = indices(ngrads)   # Indices for the leftover inverse Jacobian axes
+            ii = indices(len(f.ufl_shape))  # Indices to get to the scalar component of f
+            jj = indices(ngrads)  # Indices to sum over the local gradient axes with the inverse Jacobian
+            kk = indices(ngrads)  # Indices for the leftover inverse Jacobian axes
 
             # Preserve restricted property
             if restricted:
@@ -414,7 +421,8 @@ class OLDChangeToReferenceGrad(MultiFunction):
             for i in range(ngrads):
                 lgrad = ReferenceGrad(lgrad)
 
-            # Apply mappings with scalar indexing operations (assumes ReferenceGrad(Jinv) is zero)
+            # Apply mappings with scalar indexing operations (assumes
+            # ReferenceGrad(Jinv) is zero)
             jinv_lgrad_f = lgrad[ii+jj]
             for j, k in zip(jj, kk):
                 jinv_lgrad_f = Jinv[j, k]*jinv_lgrad_f
@@ -432,7 +440,7 @@ class OLDChangeToReferenceGrad(MultiFunction):
 
             jinv_lgrad_f = f
             for foo in range(ngrads):
-                ii = indices(len(jinv_lgrad_f.ufl_shape)) # Indices to get to the scalar component of f
+                ii = indices(len(jinv_lgrad_f.ufl_shape))  # Indices to get to the scalar component of f
                 j, k = indices(2)
 
                 lgrad = ReferenceGrad(jinv_lgrad_f)
@@ -450,7 +458,6 @@ class OLDChangeToReferenceGrad(MultiFunction):
         error("Coefficient derivatives should be expanded before applying change to reference grad.")
 
 
-
 def change_to_reference_grad(e):
     """Change Grad objects in expression to products of JacobianInverse and ReferenceGrad.
 
@@ -460,10 +467,9 @@ def change_to_reference_grad(e):
         An Expr or Form.
     """
     mf = OLDChangeToReferenceGrad()
-    #mf = NEWChangeToReferenceGrad()
+    # mf = NEWChangeToReferenceGrad()
     return map_expr_dag(mf, e)
 
-from ufl.algorithms.apply_integral_scaling import compute_integrand_scaling_factor
 
 def change_integrand_geometry_representation(integrand, scale, integral_type):
     """Change integrand geometry to the right representations."""
diff --git a/ufl/algorithms/check_arities.py b/ufl/algorithms/check_arities.py
index b9b1ae8..5e44d36 100644
--- a/ufl/algorithms/check_arities.py
+++ b/ufl/algorithms/check_arities.py
@@ -27,8 +27,9 @@ class ArityChecker(MultiFunction):
         return (o,)
 
     def nonlinear_operator(self, o):
-        # Cutoff traversal by not having *ops in argument list of this handler.
-        # Traverse only the terminals under here the fastest way we know of:
+        # Cutoff traversal by not having *ops in argument list of this
+        # handler.  Traverse only the terminals under here the fastest
+        # way we know of:
         for t in traverse_unique_terminals(o):
             if t._ufl_typecode_ == Argument._ufl_typecode_:
                 raise ArityMismatch("Applying nonlinear operator {0} to expression depending on form argument {1}.".format(o._ufl_class_.__name__, t))
@@ -48,14 +49,16 @@ class ArityChecker(MultiFunction):
 
     def product(self, o, a, b):
         if a and b:
-            # Check that we don't have test*test, trial*trial, even for different parts in a block system
+            # Check that we don't have test*test, trial*trial, even
+            # for different parts in a block system
             anumbers = set(x.number() for x in a)
             for x in b:
                 if x.number() in anumbers:
                     raise ArityMismatch("Multiplying expressions with overlapping form argument number {0}, argument is {1}.".format(x.number(), x))
             # Combine argument lists
             c = tuple(sorted(set(a + b), key=lambda x: (x.number(), x.part())))
-            # Check that we don't have any arguments shared between a and b
+            # Check that we don't have any arguments shared between a
+            # and b
             if len(c) != len(a) + len(b):
                 raise ArityMismatch("Multiplying expressions with overlapping form arguments {0} vs {1}.".format(a, b))
             # It's fine for argument parts to overlap
@@ -86,7 +89,8 @@ class ArityChecker(MultiFunction):
     reference_grad = linear_operator
     reference_value = linear_operator
 
-    # Does it make sense to have a Variable(Argument)? I see no problem.
+    # Does it make sense to have a Variable(Argument)? I see no
+    # problem.
     def variable(self, o, f, l):
         return f
 
@@ -104,7 +108,8 @@ class ArityChecker(MultiFunction):
             # Allow conditional(c, test, test)
             return a
         else:
-            # Do not allow e.g. conditional(c, test, trial), conditional(c, test, nonzeroconstant)
+            # Do not allow e.g. conditional(c, test, trial),
+            # conditional(c, test, nonzeroconstant)
             raise ArityMismatch("Conditional subexpressions with non-matching form arguments {0} vs {1}.".format(a, b))
 
     def linear_indexed_type(self, o, a, i):
@@ -118,9 +123,10 @@ class ArityChecker(MultiFunction):
     def list_tensor(self, o, *ops):
         args = set(chain(*ops))
         if args:
-            # Check that each list tensor component has the same argument numbers (ignoring parts)
+            # Check that each list tensor component has the same
+            # argument numbers (ignoring parts)
             numbers = set(tuple(sorted(set(arg.number() for arg in op))) for op in ops)
-            if () in numbers: # Allow e.g. <v[0], 0, v[1]> but not <v[0], u[0]>
+            if () in numbers:  # Allow e.g. <v[0], 0, v[1]> but not <v[0], u[0]>
                 numbers.remove(())
             if len(numbers) > 1:
                 raise ArityMismatch("Listtensor components must depend on the same argument numbers, found {0}.".format(numbers))
@@ -131,13 +137,16 @@ class ArityChecker(MultiFunction):
             # No argument dependencies
             return self._et
 
+
 def check_integrand_arity(expr, arguments):
-    arguments = tuple(sorted(set(arguments), key=lambda x: (x.number(), x.part())))
+    arguments = tuple(sorted(set(arguments),
+                             key=lambda x: (x.number(), x.part())))
     rules = ArityChecker(arguments)
     args = map_expr_dag(rules, expr, compress=False)
     if args != arguments:
         raise ArityMismatch("Integrand arguments {0} differ from form arguments {1}.".format(args, arguments))
 
+
 def check_form_arity(form, arguments):
     for itg in form.integrals():
         check_integrand_arity(itg.integrand(), arguments)
diff --git a/ufl/algorithms/check_restrictions.py b/ufl/algorithms/check_restrictions.py
index a844391..2a2d439 100644
--- a/ufl/algorithms/check_restrictions.py
+++ b/ufl/algorithms/check_restrictions.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Algorithms related to restrictions."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,14 +18,14 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
-from ufl.core.expr import Expr
-from ufl.classes import Measure
-from ufl.assertions import ufl_assert
-from ufl.algorithms.transformer import Transformer
+from ufl.log import error
+from ufl.corealg.multifunction import MultiFunction
+from ufl.corealg.map_dag import map_expr_dag
 
-class RestrictionChecker(Transformer):
+
+class RestrictionChecker(MultiFunction):
     def __init__(self, require_restriction):
-        Transformer.__init__(self)
+        MultiFunction.__init__(self)
         self.current_restriction = None
         self.require_restriction = require_restriction
 
@@ -33,8 +33,8 @@ class RestrictionChecker(Transformer):
         pass
 
     def restricted(self, o):
-        ufl_assert(self.current_restriction is None,
-            "Not expecting twice restricted expression.")
+        if self.current_restriction is not None:
+            error("Not expecting twice restricted expression.")
         self.current_restriction = o._side
         e, = o.ufl_operands
         self.visit(e)
@@ -42,20 +42,22 @@ class RestrictionChecker(Transformer):
 
     def facet_normal(self, o):
         if self.require_restriction:
-            ufl_assert(self.current_restriction is not None,
-                       "Facet normal must be restricted in interior facet integrals.")
+            if self.current_restriction is None:
+                error("Facet normal must be restricted in interior facet integrals.")
         else:
-            ufl_assert(self.current_restriction is None,
-                       "Restrictions are only allowed for interior facet integrals.")
+            if self.current_restriction is not None:
+                error("Restrictions are only allowed for interior facet integrals.")
 
     def form_argument(self, o):
         if self.require_restriction:
-            ufl_assert(self.current_restriction is not None,
-                       "Form argument must be restricted in interior facet integrals.")
+            if self.current_restriction is None:
+                error("Form argument must be restricted in interior facet integrals.")
         else:
-            ufl_assert(self.current_restriction is None,
-                       "Restrictions are only allowed for interior facet integrals.")
+            if self.current_restriction is not None:
+                error("Restrictions are only allowed for interior facet integrals.")
+
 
 def check_restrictions(expression, require_restriction):
-    ufl_assert(isinstance(expression, Expr), "Expecting Expr instance.")
-    return RestrictionChecker(require_restriction).visit(expression)
+    "Check that types that must be restricted are restricted in expression."
+    rules = RestrictionChecker(require_restriction)
+    return map_expr_dag(rules, expression)
diff --git a/ufl/algorithms/checks.py b/ufl/algorithms/checks.py
index 3ece493..dcb952a 100644
--- a/ufl/algorithms/checks.py
+++ b/ufl/algorithms/checks.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Functions to check the validity of forms."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,38 +21,37 @@
 # Modified by Anders Logg, 2008-2009.
 # Modified by Mehdi Nikbakht, 2010.
 
-from ufl.log import warning, error
+from ufl.log import error
 
 # UFL classes
+from ufl.core.expr import ufl_err_str
 from ufl.form import Form
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
 from ufl.constantvalue import is_true_ufl_scalar
-from ufl.integral import Measure
 
 # UFL algorithms
 from ufl.algorithms.traversal import iter_expressions
 from ufl.corealg.traversal import traverse_unique_terminals
 from ufl.algorithms.check_restrictions import check_restrictions
-from ufl.measure import integral_type_to_measure_name
 
-def validate_form(form): # TODO: Can we make this return a list of errors instead of raising exception?
+
+def validate_form(form):  # TODO: Can we make this return a list of errors instead of raising exception?
     """Performs all implemented validations on a form. Raises exception if something fails."""
     errors = []
-    warnings = []
 
     if not isinstance(form, Form):
-        msg = "Validation failed, not a Form:\n%s" % repr(form)
+        msg = "Validation failed, not a Form:\n%s" % ufl_err_str(form)
         error(msg)
-        #errors.append(msg)
-        #return errors
+        # errors.append(msg)
+        # return errors
 
     # FIXME: There's a bunch of other checks we should do here.
 
     # FIXME: Add back check for multilinearity
     # Check that form is multilinear
-    #if not is_multilinear(form):
-    #    errors.append("Form is not multilinear in arguments.")
+    # if not is_multilinear(form):
+    #     errors.append("Form is not multilinear in arguments.")
 
     # FIXME DOMAIN: Add check for consistency between domains somehow
     domains = set(t.ufl_domain()
@@ -68,8 +67,8 @@ def validate_form(form): # TODO: Can we make this return a list of errors instea
     elif len(cells) > 1:
         errors.append("Multiple cell definitions in form: %s" % str(cells))
 
-    # Check that no Coefficient or Argument instance
-    # have the same count unless they are the same
+    # Check that no Coefficient or Argument instance have the same
+    # count unless they are the same
     coefficients = {}
     arguments = {}
     for e in iter_expressions(form):
@@ -80,7 +79,8 @@ def validate_form(form): # TODO: Can we make this return a list of errors instea
                     g = coefficients[c]
                     if f is not g:
                         errors.append("Found different Coefficients with " +
-                                   "same count: %s and %s." % (repr(f), repr(g)))
+                                      "same count: %s and %s." % (repr(f),
+                                                                  repr(g)))
                 else:
                     coefficients[c] = f
 
@@ -104,19 +104,21 @@ def validate_form(form): # TODO: Can we make this return a list of errors instea
     # Check that all integrands are scalar
     for expression in iter_expressions(form):
         if not is_true_ufl_scalar(expression):
-            errors.append("Found non-scalar integrand expression:\n%s\n%s" %
-                              (str(expression), repr(expression)))
+            errors.append("Found non-scalar integrand expression: %s\n" %
+                          ufl_err_str(expression))
 
     # Check that restrictions are permissible
     for integral in form.integrals():
-        # Only allow restrictions on interior facet integrals and surface measures
+        # Only allow restrictions on interior facet integrals and
+        # surface measures
         if integral.integral_type().startswith("interior_facet"):
             check_restrictions(integral.integrand(), True)
         else:
             check_restrictions(integral.integrand(), False)
 
     # Raise exception with all error messages
-    # TODO: Return errors list instead, need to collect messages from all validations above first.
+    # TODO: Return errors list instead, need to collect messages from
+    # all validations above first.
     if errors:
         final_msg = 'Found errors in validation of form:\n%s' % '\n\n'.join(errors)
         error(final_msg)
diff --git a/ufl/algorithms/compute_form_data.py b/ufl/algorithms/compute_form_data.py
index 48c9398..3388bbf 100644
--- a/ufl/algorithms/compute_form_data.py
+++ b/ufl/algorithms/compute_form_data.py
@@ -3,7 +3,7 @@
 will typically call prior to code generation to preprocess/simplify a
 raw input form given by a user."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -22,13 +22,12 @@ raw input form given by a user."""
 
 from itertools import chain
 
-from ufl.log import error, warning, info
-from ufl.assertions import ufl_assert
+from ufl.log import error, info
 
 from ufl.classes import GeometricFacetQuantity, Coefficient, Form
 from ufl.corealg.traversal import traverse_unique_terminals
 from ufl.algorithms.analysis import extract_coefficients, extract_sub_elements, unique_tuple
-from ufl.algorithms.formdata import FormData#, ExprData
+from ufl.algorithms.formdata import FormData
 from ufl.algorithms.formtransformations import compute_form_arities
 from ufl.algorithms.check_arities import check_form_arity
 from ufl.algorithms.elementtransformations import reconstruct_element
@@ -39,7 +38,7 @@ from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
 from ufl.algorithms.apply_derivatives import apply_derivatives
 from ufl.algorithms.apply_integral_scaling import apply_integral_scaling
 from ufl.algorithms.apply_geometry_lowering import apply_geometry_lowering
-from ufl.algorithms.apply_restrictions import apply_restrictions
+from ufl.algorithms.apply_restrictions import apply_restrictions, apply_default_restrictions
 from ufl.algorithms.estimate_degrees import estimate_total_polynomial_degree
 
 # See TODOs at the call sites of these below:
@@ -55,18 +54,23 @@ def _auto_select_degree(elements):
     used by DOLFIN to allow the specification of Expressions with
     undefined degrees.
     """
-    # Use max degree of all elements, at least 1 (to work with Lagrange elements)
-    return max({ e.degree() for e in elements } - { None } | { 1 })
+    # Use max degree of all elements, at least 1 (to work with
+    # Lagrange elements)
+    return max({e.degree() for e in elements} - {None} | {1})
 
 
 def _compute_element_mapping(form):
     "Compute element mapping for element replacement"
-    # The element mapping is a slightly messy concept with two use cases:
-    # - Expression with missing cell or element TODO: Implement proper Expression handling in UFL and get rid of this
-    # - Constant with missing cell TODO: Fix anything that needs to be worked around to drop this requirement
+    # The element mapping is a slightly messy concept with two use
+    # cases:
+    # - Expression with missing cell or element TODO: Implement proper
+    #   Expression handling in UFL and get rid of this
+    # - Constant with missing cell TODO: Fix anything that needs to be
+    #   worked around to drop this requirement
 
     # Extract all elements and include subelements of mixed elements
-    elements = [obj.ufl_element() for obj in chain(form.arguments(), form.coefficients())]
+    elements = [obj.ufl_element() for obj in chain(form.arguments(),
+                                                   form.coefficients())]
     elements = extract_sub_elements(elements)
 
     # Try to find a common degree for elements
@@ -83,10 +87,10 @@ def _compute_element_mapping(form):
         cell = element.cell()
         if cell is None:
             domains = form.ufl_domains()
-            ufl_assert(len(domains) == 1,
-                       "Cannot replace unknown element cell without unique common cell in form.")
-            domain, = domains
-            cell = domain.ufl_cell()
+            if not all(domains[0].ufl_cell() == d.ufl_cell()
+                       for d in domains):
+                error("Cannot replace unknown element cell without unique common cell in form.")
+            cell = domains[0].ufl_cell()
             info("Adjusting missing element cell to %s." % (cell,))
             reconstruct = True
 
@@ -100,7 +104,8 @@ def _compute_element_mapping(form):
         # Reconstruct element and add to map
         if reconstruct:
             element_mapping[element] = reconstruct_element(element,
-                    element.family(), cell, degree)
+                                                           element.family(),
+                                                           cell, degree)
         else:
             element_mapping[element] = element
 
@@ -122,29 +127,33 @@ def _compute_max_subdomain_ids(integral_data):
 
 
 def _compute_form_data_elements(self, arguments, coefficients, domains):
-    self.argument_elements    = tuple(f.ufl_element() for f in arguments)
+    self.argument_elements = tuple(f.ufl_element() for f in arguments)
     self.coefficient_elements = tuple(f.ufl_element() for f in coefficients)
-    self.coordinate_elements  = tuple(domain.ufl_coordinate_element() for domain in domains)
+    self.coordinate_elements = tuple(domain.ufl_coordinate_element() for domain in domains)
 
-    # TODO: Include coordinate elements from argument and coefficient domains as well? Can they differ?
+    # TODO: Include coordinate elements from argument and coefficient
+    # domains as well? Can they differ?
 
-    # Note: Removed self.elements and self.sub_elements to make sure code that
-    #       depends on the selection of argument + coefficient elements blow up,
-    #       as opposed to silently almost working, with the introduction of the coordinate elements here.
+    # Note: Removed self.elements and self.sub_elements to make sure
+    #       code that depends on the selection of argument +
+    #       coefficient elements blow up, as opposed to silently
+    #       almost working, with the introduction of the coordinate
+    #       elements here.
 
     all_elements = self.argument_elements + self.coefficient_elements + self.coordinate_elements
     all_sub_elements = extract_sub_elements(all_elements)
 
-    self.unique_elements      = unique_tuple(all_elements)
-    self.unique_sub_elements  = unique_tuple(all_sub_elements)
+    self.unique_elements = unique_tuple(all_elements)
+    self.unique_sub_elements = unique_tuple(all_sub_elements)
 
 
 def _check_elements(form_data):
-    for element in chain(form_data.unique_elements, form_data.unique_sub_elements):
-        ufl_assert(element.family() is not None,
-                   "Found element with undefined familty: %s" % repr(element))
-        ufl_assert(element.cell() is not None,
-                   "Found element with undefined cell: %s" % repr(element))
+    for element in chain(form_data.unique_elements,
+                         form_data.unique_sub_elements):
+        if element.family() is None:
+            error("Found element with undefined familty: %s" % repr(element))
+        if element.cell() is None:
+            error("Found element with undefined cell: %s" % repr(element))
 
 
 def _check_facet_geometry(integral_data):
@@ -152,7 +161,8 @@ def _check_facet_geometry(integral_data):
         for itg in itg_data.integrals:
             it = itg_data.integral_type
             # Facet geometry is only valid in facet integrals.
-            # Allowing custom integrals to pass as well, although that's not really strict enough.
+            # Allowing custom integrals to pass as well, although
+            # that's not really strict enough.
             if not ("facet" in it or "custom" in it or "interface" in it):
                 # Not a facet integral
                 for expr in traverse_unique_terminals(itg.integrand()):
@@ -162,10 +172,12 @@ def _check_facet_geometry(integral_data):
 
 
 def _check_form_arity(preprocessed_form):
-    # Check that we don't have a mixed linear/bilinear form or anything like that
-    # FIXME: This is slooow and should be moved to form compiler and/or replaced with something faster
-    ufl_assert(len(compute_form_arities(preprocessed_form)) == 1,
-               "All terms in form must have same rank.")
+    # Check that we don't have a mixed linear/bilinear form or
+    # anything like that
+    # FIXME: This is slooow and should be moved to form compiler
+    # and/or replaced with something faster
+    if 1 != len(compute_form_arities(preprocessed_form)):
+        error("All terms in form must have same rank.")
 
 
 def _build_coefficient_replace_map(coefficients, element_mapping=None):
@@ -186,6 +198,7 @@ def _build_coefficient_replace_map(coefficients, element_mapping=None):
 
     return new_coefficients, replace_map
 
+
 def attach_estimated_degrees(form):
     """Attach estimated polynomial degree to a form's integrals.
 
@@ -203,12 +216,14 @@ def attach_estimated_degrees(form):
         new_integrals.append(integral.reconstruct(metadata=md))
     return Form(new_integrals)
 
+
 def compute_form_data(form,
                       # Default arguments configured to behave the way old FFC expects it:
                       do_apply_function_pullbacks=False,
                       do_apply_integral_scaling=False,
                       do_apply_geometry_lowering=False,
                       preserve_geometry_types=(),
+                      do_apply_default_restrictions=True,
                       do_apply_restrictions=True,
                       do_estimate_degrees=True,
                       ):
@@ -224,19 +239,20 @@ def compute_form_data(form,
     # See 'reduced_coefficients' below.
     self.original_form = form
 
-
     # --- Pass form integrands through some symbolic manipulation
 
-    # Note: Default behaviour here will process form the way that is currently expected by vanilla FFC
+    # Note: Default behaviour here will process form the way that is
+    # currently expected by vanilla FFC
 
     # Lower abstractions for tensor-algebra types into index notation,
-    # reducing the number of operators later algorithms and form compilers
-    # need to handle
+    # reducing the number of operators later algorithms and form
+    # compilers need to handle
     form = apply_algebra_lowering(form)
 
-    # Apply differentiation before function pullbacks, because for example
-    # coefficient derivatives are more complicated to derive after coefficients
-    # are rewritten, and in particular for user-defined coefficient relations it just gets too messy
+    # Apply differentiation before function pullbacks, because for
+    # example coefficient derivatives are more complicated to derive
+    # after coefficients are rewritten, and in particular for
+    # user-defined coefficient relations it just gets too messy
     form = apply_derivatives(form)
 
     # --- Group form integrals
@@ -252,29 +268,37 @@ def compute_form_data(form,
         form = attach_estimated_degrees(form)
 
     if do_apply_function_pullbacks:
-        # Rewrite coefficients and arguments in terms of their reference cell values
-        # with Piola transforms and symmetry transforms injected where needed.
-        # Decision: Not supporting grad(dolfin.Expression) without a Domain.
-        #           Current dolfin works if Expression has a cell
-        #           but this should be changed to a mesh.
+        # Rewrite coefficients and arguments in terms of their
+        # reference cell values with Piola transforms and symmetry
+        # transforms injected where needed.
+        # Decision: Not supporting grad(dolfin.Expression) without a
+        #           Domain.  Current dolfin works if Expression has a
+        #           cell but this should be changed to a mesh.
         form = apply_function_pullbacks(form)
 
     # Scale integrals to reference cell frames
     if do_apply_integral_scaling:
         form = apply_integral_scaling(form)
 
-    # Lower abstractions for geometric quantities into a smaller set of quantities,
-    # allowing the form compiler to deal with a smaller set of types and treating
-    # geometric quantities like any other expressions w.r.t. loop-invariant code motion etc.
+    # Apply default restriction to fully continuous terminals
+    if do_apply_default_restrictions:
+        form = apply_default_restrictions(form)
+
+    # Lower abstractions for geometric quantities into a smaller set
+    # of quantities, allowing the form compiler to deal with a smaller
+    # set of types and treating geometric quantities like any other
+    # expressions w.r.t. loop-invariant code motion etc.
     if do_apply_geometry_lowering:
         form = apply_geometry_lowering(form, preserve_geometry_types)
 
-    # Apply differentiation again, because the algorithms above can generate
-    # new derivatives or rewrite expressions inside derivatives
+    # Apply differentiation again, because the algorithms above can
+    # generate new derivatives or rewrite expressions inside
+    # derivatives
     if do_apply_function_pullbacks or do_apply_geometry_lowering:
         form = apply_derivatives(form)
 
-        # Neverending story: apply_derivatives introduces new Jinvs, which needs more geometry lowering
+        # Neverending story: apply_derivatives introduces new Jinvs,
+        # which needs more geometry lowering
         if do_apply_geometry_lowering:
             form = apply_geometry_lowering(form, preserve_geometry_types)
             # Lower derivatives that may have appeared
@@ -284,12 +308,10 @@ def compute_form_data(form,
     if do_apply_restrictions:
         form = apply_restrictions(form)
 
-
     # --- Group integrals into IntegralData objects
     # Most of the heavy lifting is done above in group_form_integrals.
     self.integral_data = build_integral_data(form.integrals())
 
-
     # --- Create replacements for arguments and coefficients
 
     # Figure out which form coefficients each integral should enable
@@ -301,22 +323,24 @@ def compute_form_data(form,
         # Store with IntegralData object
         itg_data.integral_coefficients = itg_coeffs
 
-    # Figure out which coefficients from the original form are actually used in any integral
-    # (Differentiation may reduce the set of coefficients w.r.t. the original form)
+    # Figure out which coefficients from the original form are
+    # actually used in any integral (Differentiation may reduce the
+    # set of coefficients w.r.t. the original form)
     reduced_coefficients_set = set()
     for itg_data in self.integral_data:
         reduced_coefficients_set.update(itg_data.integral_coefficients)
-    self.reduced_coefficients = sorted(reduced_coefficients_set, key=lambda c: c.count())
+    self.reduced_coefficients = sorted(reduced_coefficients_set,
+                                       key=lambda c: c.count())
     self.num_coefficients = len(self.reduced_coefficients)
     self.original_coefficient_positions = [i for i, c in enumerate(self.original_form.coefficients())
                                            if c in self.reduced_coefficients]
 
-    # Store back into integral data which form coefficients are used by each integral
+    # Store back into integral data which form coefficients are used
+    # by each integral
     for itg_data in self.integral_data:
         itg_data.enabled_coefficients = [bool(coeff in itg_data.integral_coefficients)
                                          for coeff in self.reduced_coefficients]
 
-
     # --- Collect some trivial data
 
     # Get rank of form from argument list (assuming not a mixed arity form)
@@ -325,43 +349,48 @@ def compute_form_data(form,
     # Extract common geometric dimension (topological is not common!)
     self.geometric_dimension = self.original_form.integrals()[0].ufl_domain().geometric_dimension()
 
-
-    # --- Build mapping from old incomplete element objects to new well defined elements.
-    # This is to support the Expression construct in dolfin which subclasses Coefficient
-    # but doesn't provide an element, and the Constant construct that doesn't provide
-    # the domain that a Coefficient is supposed to have. A future design iteration in
-    # UFL/UFC/FFC/DOLFIN may allow removal of this mapping with the introduction of UFL
-    # types for Expression-like functions that can be evaluated in quadrature points.
+    # --- Build mapping from old incomplete element objects to new
+    # well defined elements.  This is to support the Expression
+    # construct in dolfin which subclasses Coefficient but doesn't
+    # provide an element, and the Constant construct that doesn't
+    # provide the domain that a Coefficient is supposed to have. A
+    # future design iteration in UFL/UFC/FFC/DOLFIN may allow removal
+    # of this mapping with the introduction of UFL types for
+    # Expression-like functions that can be evaluated in quadrature
+    # points.
     self.element_replace_map = _compute_element_mapping(self.original_form)
 
-    # Mappings from elements and coefficients
-    # that reside in form to objects with canonical numbering as well as
-    # completed cells and elements
+    # Mappings from elements and coefficients that reside in form to
+    # objects with canonical numbering as well as completed cells and
+    # elements
     renumbered_coefficients, function_replace_map = \
-        _build_coefficient_replace_map(self.reduced_coefficients, self.element_replace_map)
+        _build_coefficient_replace_map(self.reduced_coefficients,
+                                       self.element_replace_map)
     self.function_replace_map = function_replace_map
 
-    # --- Store various lists of elements and sub elements (adds members to self)
+    # --- Store various lists of elements and sub elements (adds
+    #     members to self)
     _compute_form_data_elements(self,
                                 self.original_form.arguments(),
                                 renumbered_coefficients,
                                 self.original_form.ufl_domains())
 
     # --- Store number of domains for integral types
-    # TODO: Group this by domain first. For now keep a backwards compatible data structure.
+    # TODO: Group this by domain first. For now keep a backwards
+    # compatible data structure.
     self.max_subdomain_ids = _compute_max_subdomain_ids(self.integral_data)
 
-
     # --- Checks
     _check_elements(self)
     _check_facet_geometry(self.integral_data)
 
-    # TODO: This is a very expensive check... Replace with something faster!
+    # TODO: This is a very expensive check... Replace with something
+    # faster!
     preprocessed_form = reconstruct_form_from_integral_data(self.integral_data)
-    #_check_form_arity(preprocessed_form)
-    check_form_arity(preprocessed_form, self.original_form.arguments()) # Currently testing how fast this is
+    check_form_arity(preprocessed_form, self.original_form.arguments())  # Currently testing how fast this is
 
-    # TODO: This member is used by unit tests, change the tests to remove this!
+    # TODO: This member is used by unit tests, change the tests to
+    # remove this!
     self.preprocessed_form = preprocessed_form
 
     return self
diff --git a/ufl/algorithms/domain_analysis.py b/ufl/algorithms/domain_analysis.py
index 1a8ffa5..a5ed720 100644
--- a/ufl/algorithms/domain_analysis.py
+++ b/ufl/algorithms/domain_analysis.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithms for building canonical data structure for integrals over subdomains."""
 
-# Copyright (C) 2009-2015 Anders Logg and Martin Sandve Alnæs
+# Copyright (C) 2009-2016 Anders Logg and Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,20 +18,21 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+# import six
 from collections import defaultdict
 from six.moves import zip
-from six import iteritems
 
 import ufl
 from ufl.log import error
-from ufl.assertions import ufl_assert
-from ufl.measure import Measure
+from ufl.utils.py23 import as_native_strings
 from ufl.integral import Integral
 from ufl.form import Form
 from ufl.sorting import cmp_expr, sorted_expr
 from ufl.utils.sorting import canonicalize_metadata, sorted_by_key, sorted_by_tuple_key
+import numbers
 
 
+# @six.python_2_unicode_compatible
 class IntegralData(object):
     """Utility class with the members
         (domain, integral_type, subdomain_id, integrals, metadata)
@@ -39,15 +40,17 @@ class IntegralData(object):
     where metadata is an empty dictionary that may be used for
     associating metadata with each object.
     """
-    __slots__ = ('domain', 'integral_type', 'subdomain_id', 'integrals', 'metadata',
-                 'integral_coefficients', 'enabled_coefficients')
-    def __init__(self, domain, integral_type, subdomain_id, integrals, metadata):
-        ufl_assert(len(set(itg.ufl_domain() for itg in integrals)) == 1,
-                   "Multiple domains mismatch in integral data.")
-        ufl_assert(all(integral_type == itg.integral_type() for itg in integrals),
-                   "Integral type mismatch in integral data.")
-        ufl_assert(all(subdomain_id == itg.subdomain_id() for itg in integrals),
-                   "Subdomain id mismatch in integral data.")
+    __slots__ = as_native_strings(('domain', 'integral_type', 'subdomain_id', 'integrals',
+                 'metadata', 'integral_coefficients', 'enabled_coefficients'))
+
+    def __init__(self, domain, integral_type, subdomain_id, integrals,
+                 metadata):
+        if 1 != len(set(itg.ufl_domain() for itg in integrals)):
+            error("Multiple domains mismatch in integral data.")
+        if not all(integral_type == itg.integral_type() for itg in integrals):
+            error("Integral type mismatch in integral data.")
+        if not all(subdomain_id == itg.subdomain_id() for itg in integrals):
+            error("Subdomain id mismatch in integral data.")
 
         self.domain = domain
         self.integral_type = integral_type
@@ -55,17 +58,21 @@ class IntegralData(object):
 
         self.integrals = integrals
 
-        # This is populated in preprocess using data not available at this stage:
+        # This is populated in preprocess using data not available at
+        # this stage:
         self.integral_coefficients = None
         self.enabled_coefficients = None
 
-        # TODO: I think we can get rid of this with some refactoring in ffc:
+        # TODO: I think we can get rid of this with some refactoring
+        # in ffc:
         self.metadata = metadata
 
     def __lt__(self, other):
         # To preserve behaviour of extract_integral_data:
-        return ((self.integral_type, self.subdomain_id, self.integrals, self.metadata)
-                < (other.integral_type, other.subdomain_id, other.integrals, other.metadata))
+        return ((self.integral_type, self.subdomain_id,
+                 self.integrals, self.metadata) <
+                (other.integral_type, other.subdomain_id, other.integrals,
+                 other.metadata))
 
     def __eq__(self, other):
         # Currently only used for tests:
@@ -74,10 +81,16 @@ class IntegralData(object):
                 self.integrals == other.integrals and
                 self.metadata == other.metadata)
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
-        return "IntegralData object over domain (%s, %s), with integrals:\n%s\nand metadata:\n%s" % (
+        s = "IntegralData over domain(%s, %s), with integrals:\n%s\nand metadata:\n%s" % (
             self.integral_type, self.subdomain_id,
             '\n\n'.join(map(str, self.integrals)), self.metadata)
+        return s
+
 
 def dicts_lt(a, b):
     na = 0 if a is None else len(a)
@@ -87,16 +100,19 @@ def dicts_lt(a, b):
     for ia, ib in zip(sorted_by_key(a), sorted_by_key(b)):
         # Assuming keys are sortable (usually str)
         if ia[0] != ib[0]:
-            return (ia[0].__class__.__name__, ia[0]) < (ib[0].__class__.__name__, ib[0]) # Hack to preserve type sorting in py3
+            return (ia[0].__class__.__name__, ia[0]) < (ib[0].__class__.__name__, ib[0])  # Hack to preserve type sorting in py3
         # Assuming values are sortable
         if ia[1] != ib[1]:
-            return (ia[1].__class__.__name__, ia[1]) < (ib[1].__class__.__name__, ib[1]) # Hack to preserve type sorting in py3
+            return (ia[1].__class__.__name__, ia[1]) < (ib[1].__class__.__name__, ib[1])  # Hack to preserve type sorting in py3
+
 
 # Tuple comparison helper
 class ExprTupleKey(object):
-    __slots__ = ('x',)
+    __slots__ = as_native_strings(('x',))
+
     def __init__(self, x):
         self.x = x
+
     def __lt__(self, other):
         # Comparing expression first
         c = cmp_expr(self.x[0], other.x[0])
@@ -110,6 +126,7 @@ class ExprTupleKey(object):
             mdo = canonicalize_metadata(other.x[1])
             return mds < mdo
 
+
 def group_integrals_by_domain_and_type(integrals, domains):
     """
     Input:
@@ -119,10 +136,10 @@ def group_integrals_by_domain_and_type(integrals, domains):
     Output:
         integrals_by_domain_and_type: dict: (domain, integral_type) -> list(Integral)
     """
-    integral_data = []
     integrals_by_domain_and_type = defaultdict(list)
     for itg in integrals:
-        ufl_assert(itg.ufl_domain() is not None, "Integrals without a domain is now illegal.")
+        if itg.ufl_domain() is None:
+            error("Integral has no domain.")
         key = (itg.ufl_domain(), itg.integral_type())
 
         # Append integral to list of integrals with shared key
@@ -130,14 +147,15 @@ def group_integrals_by_domain_and_type(integrals, domains):
 
     return integrals_by_domain_and_type
 
+
 def integral_subdomain_ids(integral):
     "Get a tuple of integer subdomains or a valid string subdomain from integral."
     did = integral.subdomain_id()
-    if isinstance(did, int):
+    if isinstance(did, numbers.Integral):
         return (did,)
     elif isinstance(did, tuple):
-        ufl_assert(all(isinstance(d, int) for d in did),
-                   "Expecting only integer subdomains in tuple.")
+        if not all(isinstance(d, numbers.Integral) for d in did):
+            error("Expecting only integer subdomains in tuple.")
         return did
     elif did in ("everywhere", "otherwise"):
         # TODO: Define list of valid strings somewhere more central
@@ -145,6 +163,7 @@ def integral_subdomain_ids(integral):
     else:
         error("Invalid domain id %s." % did)
 
+
 def rearrange_integrals_by_single_subdomains(integrals):
     """Rearrange integrals over multiple subdomains to single subdomain integrals.
 
@@ -167,7 +186,8 @@ def rearrange_integrals_by_single_subdomains(integrals):
             subdomain_integrals.append((dids, itg))
 
     # Fill single_subdomain_integrals with lists of integrals from
-    # subdomain_integrals, but split and restricted to single subdomain ids
+    # subdomain_integrals, but split and restricted to single
+    # subdomain ids
     single_subdomain_integrals = defaultdict(list)
     for dids, itg in subdomain_integrals:
         # Region or single subdomain id
@@ -175,7 +195,8 @@ def rearrange_integrals_by_single_subdomains(integrals):
             # Restrict integral to this subdomain!
             single_subdomain_integrals[did].append(itg.reconstruct(subdomain_id=did))
 
-    # Add everywhere integrals to each single subdomain id integral list
+    # Add everywhere integrals to each single subdomain id integral
+    # list
     otherwise_integrals = []
     for ev_itg in everywhere_integrals:
         # Restrict everywhere integral to 'otherwise'
@@ -214,7 +235,8 @@ def accumulate_integrands_with_same_metadata(integrals):
             by_cdid[cdid] = ([], cd)
         by_cdid[cdid][0].append(itg)
 
-    # Accumulate integrands separately for each compiler data object id
+    # Accumulate integrands separately for each compiler data object
+    # id
     for cdid in by_cdid:
         integrals, cd = by_cdid[cdid]
         # Ensure canonical sorting of more than two integrands
@@ -222,7 +244,8 @@ def accumulate_integrands_with_same_metadata(integrals):
         integrands_sum = sum(integrands[1:], integrands[0])
         by_cdid[cdid] = (integrands_sum, cd)
 
-    # Sort integrands canonically by integrand first then compiler data
+    # Sort integrands canonically by integrand first then compiler
+    # data
     return sorted(by_cdid.values(), key=ExprTupleKey)
 
 
@@ -284,7 +307,8 @@ def group_form_integrals(form, domains):
                 rearrange_integrals_by_single_subdomains(ddt_integrals)
 
             for subdomain_id, ss_integrals in sorted_by_key(single_subdomain_integrals):
-                # Accumulate integrands of integrals that share the same compiler data
+                # Accumulate integrands of integrals that share the
+                # same compiler data
                 integrands_and_cds = \
                     accumulate_integrands_with_same_metadata(ss_integrals)
 
@@ -293,6 +317,7 @@ def group_form_integrals(form, domains):
                                               subdomain_id, metadata, None))
     return Form(integrals)
 
+
 def reconstruct_form_from_integral_data(integral_data):
     integrals = []
     for ida in integral_data:
diff --git a/ufl/algorithms/elementtransformations.py b/ufl/algorithms/elementtransformations.py
index ebc5eaa..0c364c9 100644
--- a/ufl/algorithms/elementtransformations.py
+++ b/ufl/algorithms/elementtransformations.py
@@ -20,10 +20,13 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 from ufl.finiteelement import FiniteElement, VectorElement, TensorElement, \
-        MixedElement, EnrichedElement
+    MixedElement, EnrichedElement
+
+__all__ = as_native_strings(['increase_order', 'tear'])
 
-__all__ = ['increase_order', 'tear']
 
 def increase_order(element):
     "Return element of same family, but a polynomial degree higher."
@@ -51,7 +54,8 @@ def reconstruct_element(element, family, cell, degree):
     elif isinstance(element, TensorElement):
         return TensorElement(family, cell, degree, shape=element.value_shape())
     else:
-        error("Element reconstruction is only done to stay compatible with hacks in DOLFIN. Not expecting a %r" % (element,))
+        error("Element reconstruction is only done to stay compatible"
+              " with hacks in DOLFIN. Not expecting a %s" % repr(element))
 
 
 def _increase_degree(element, degree_rise):
@@ -65,7 +69,8 @@ def _increase_degree(element, degree_rise):
         return EnrichedElement([_increase_degree(e, degree_rise)
                                 for e in element.sub_elements()])
     else:
-        error("Element reconstruction is only done to stay compatible with hacks in DOLFIN. Not expecting a %r" % (element,))
+        error("Element reconstruction is only done to stay compatible"
+              " with hacks in DOLFIN. Not expecting a %s" % repr(element))
 
 
 def _change_family(element, family):
@@ -78,4 +83,5 @@ def _change_family(element, family):
         return EnrichedElement([_change_family(e, family)
                                 for e in element.sub_elements()])
     else:
-        error("Element reconstruction is only done to stay compatible with hacks in DOLFIN. Not expecting a %r" % (element,))
+        error("Element reconstruction is only done to stay compatible"
+              " with hacks in DOLFIN. Not expecting a %s" % repr(element))
diff --git a/ufl/algorithms/estimate_degrees.py b/ufl/algorithms/estimate_degrees.py
index 853f6aa..68715a4 100644
--- a/ufl/algorithms/estimate_degrees.py
+++ b/ufl/algorithms/estimate_degrees.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithms for estimating polynomial degrees of expressions."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -21,7 +21,6 @@
 # Modified by Anders Logg, 2009-2010
 # Modified by Jan Blechta, 2012
 
-from ufl.assertions import ufl_assert
 from ufl.log import warning, error
 from ufl.form import Form
 from ufl.integral import Integral
@@ -30,6 +29,14 @@ from ufl.corealg.map_dag import map_expr_dags
 from ufl.checks import is_cellwise_constant
 
 
+class IrreducibleInt(int):
+    """Degree type used by quadrilaterals.
+
+    Unlike int, values of this type are not decremeneted by _reduce_degree.
+    """
+    pass
+
+
 class SumDegreeEstimator(MultiFunction):
     "This algorithm is exact for a few operators and heuristic for many."
 
@@ -61,44 +68,56 @@ class SumDegreeEstimator(MultiFunction):
     def argument(self, v):
         """A form argument provides a degree depending on the element,
         or the default degree if the element has no degree."""
-        return v.ufl_element().degree() # FIXME: Use component to improve accuracy for mixed elements
+        return v.ufl_element().degree()  # FIXME: Use component to improve accuracy for mixed elements
 
     def coefficient(self, v):
         """A form argument provides a degree depending on the element,
         or the default degree if the element has no degree."""
         e = v.ufl_element()
         e = self.element_replace_map.get(e, e)
-        d = e.degree() # FIXME: Use component to improve accuracy for mixed elements
+        d = e.degree()  # FIXME: Use component to improve accuracy for mixed elements
         if d is None:
             d = self.default_degree
         return d
 
     def _reduce_degree(self, v, f):
         """Reduces the estimated degree by one; used when derivatives
-        are taken. Does not reduce the degree when OuterProduct elements
-        are involved."""
-        if isinstance(f, int):
+        are taken. Does not reduce the degree when TensorProduct elements
+        or quadrilateral elements are involved."""
+        if isinstance(f, int) and not isinstance(f, IrreducibleInt):
             return max(f-1, 0)
         else:
             # if tuple, do not reduce
             return f
 
     def _add_degrees(self, v, *ops):
-        if all(isinstance(o, int) for o in ops):
-            return sum(ops)
-        else:
+        def add_single(ops):
+            if any(isinstance(o, IrreducibleInt) for o in ops):
+                return IrreducibleInt(sum(ops))
+            else:
+                return sum(ops)
+
+        if any(isinstance(o, tuple) for o in ops):
             # we can add a slight hack here to handle things
             # like adding 0 to (3, 3) [by expanding
             # 0 to (0, 0) when making tempops]
             tempops = [foo if isinstance(foo, tuple) else (foo, foo) for foo in ops]
-            return tuple(map(sum, zip(*tempops)))
+            return tuple(map(add_single, zip(*tempops)))
+        else:
+            return add_single(ops)
 
     def _max_degrees(self, v, *ops):
-        if all(isinstance(o, int) for o in ops):
-            return max(ops + (0,))
-        else:
+        def max_single(ops):
+            if any(isinstance(o, IrreducibleInt) for o in ops):
+                return IrreducibleInt(max(ops))
+            else:
+                return max(ops)
+
+        if any(isinstance(o, tuple) for o in ops):
             tempops = [foo if isinstance(foo, tuple) else (foo, foo) for foo in ops]
-            return tuple(map(max, zip(*tempops)))
+            return tuple(map(max_single, zip(*tempops)))
+        else:
+            return max_single(ops + (0,))
 
     def _not_handled(self, v, *args):
         error("Missing degree handler for type %s" % v._ufl_class_.__name__)
@@ -111,35 +130,47 @@ class SumDegreeEstimator(MultiFunction):
     # Utility types with no degree concept
     def multi_index(self, v):
         return None
+
     def label(self, v):
         return None
+
     # Fall-through, indexing and similar types
     def reference_value(self, rv, f):
         return f
+
     def variable(self, v, e, l):
         return e
+
     def transposed(self, v, A):
         return A
+
     def index_sum(self, v, A, ii):
         return A
+
     def indexed(self, v, A, ii):
         return A
+
     def component_tensor(self, v, A, ii):
         return A
+
     list_tensor = _max_degrees
+
     def positive_restricted(self, v, a):
         return a
+
     def negative_restricted(self, v, a):
         return a
 
     # A sum takes the max degree of its operands:
     sum = _max_degrees
 
-    # TODO: Need a new algorithm which considers direction of derivatives of form arguments
-    # A spatial derivative reduces the degree with one
+    # TODO: Need a new algorithm which considers direction of
+    # derivatives of form arguments A spatial derivative reduces the
+    # degree with one
     grad = _reduce_degree
     reference_grad = _reduce_degree
-    # Handling these types although they should not occur... please apply preprocessing before using this algorithm:
+    # Handling these types although they should not occur... please
+    # apply preprocessing before using this algorithm:
     nabla_grad = _reduce_degree
     div = _reduce_degree
     reference_div = _reduce_degree
@@ -157,16 +188,18 @@ class SumDegreeEstimator(MultiFunction):
 
     # A product accumulates the degrees of its operands:
     product = _add_degrees
-    # Handling these types although they should not occur... please apply preprocessing before using this algorithm:
+    # Handling these types although they should not occur... please
+    # apply preprocessing before using this algorithm:
     inner = _add_degrees
     dot = _add_degrees
     outer = _add_degrees
     cross = _add_degrees
 
-    # Explicitly not handling these types, please apply preprocessing before using this algorithm:
-    derivative = _not_handled # base type
-    compound_derivative = _not_handled # base type
-    compound_tensor_operator = _not_handled # base class
+    # Explicitly not handling these types, please apply preprocessing
+    # before using this algorithm:
+    derivative = _not_handled  # base type
+    compound_derivative = _not_handled  # base type
+    compound_tensor_operator = _not_handled  # base class
     variable_derivative = _not_handled
     trace = _not_handled
     determinant = _not_handled
@@ -201,7 +234,8 @@ class SumDegreeEstimator(MultiFunction):
                 return tuple(foo*gi for foo in a)
         except:
             pass
-        # Something to a non-integer power, this is just a heuristic with no background
+        # Something to a non-integer power, this is just a heuristic
+        # with no background
         if isinstance(a, int):
             return a*2
         else:
@@ -214,13 +248,11 @@ class SumDegreeEstimator(MultiFunction):
         which can be wildly inaccurate but at least
         gives a somewhat high integration degree.
         """
-        #print "estimate",a,b
         if a or b:
             return self._add_degrees(v, self._max_degrees(v, a, b), 2)
         else:
             return self._max_degrees(v, a, b)
 
-
     def math_function(self, v, a):
         """Using the heuristic
         degree(sin(const)) == 0
@@ -266,7 +298,8 @@ class SumDegreeEstimator(MultiFunction):
     max_value = min_value
 
 
-def estimate_total_polynomial_degree(e, default_degree=1, element_replace_map={}):
+def estimate_total_polynomial_degree(e, default_degree=1,
+                                     element_replace_map={}):
     """Estimate total polynomial degree of integrand.
 
     NB! Although some compound types are supported here,
@@ -279,7 +312,8 @@ def estimate_total_polynomial_degree(e, default_degree=1, element_replace_map={}
     """
     de = SumDegreeEstimator(default_degree, element_replace_map)
     if isinstance(e, Form):
-        ufl_assert(e.integrals(), "Got form with no integrals!")
+        if not e.integrals():
+            error("Got form with no integrals!")
         degrees = map_expr_dags(de, [it.integrand() for it in e.integrals()])
     elif isinstance(e, Integral):
         degrees = map_expr_dags(de, [e.integrand()])
@@ -287,31 +321,3 @@ def estimate_total_polynomial_degree(e, default_degree=1, element_replace_map={}
         degrees = map_expr_dags(de, [e])
     degree = max(degrees) if degrees else default_degree
     return degree
-
-
-# TODO: Do these contain useful ideas or should we just delete them?
-
-
-def __unused__extract_max_quadrature_element_degree(integral):
-    """Extract quadrature integration order from quadrature
-    elements in integral. Returns None if not found."""
-    quadrature_elements = [e for e in extract_elements(integral) if "Quadrature" in e.family()]
-    degrees = [element.degree() for element in quadrature_elements]
-    degrees = [q for q in degrees if q is not None]
-    if not degrees:
-        return None
-    max_degree = quadrature_elements[0].degree()
-    ufl_assert(all(max_degree == q for q in degrees),
-               "Incompatible quadrature elements specified (orders must be equal).")
-    return max_degree
-
-
-def __unused__estimate_quadrature_degree(integral):
-    "Estimate the necessary quadrature order for integral using the sum of argument degrees."
-    arguments = extract_arguments(integral)
-    degrees = [v.ufl_element().degree() for v in arguments]
-    if len(arguments) == 0:
-        return None
-    if len(arguments) == 1:
-        return 2*degrees[0]
-    return sum(degrees)
diff --git a/ufl/algorithms/expand_compounds.py b/ufl/algorithms/expand_compounds.py
index 70a92ec..94a8d58 100644
--- a/ufl/algorithms/expand_compounds.py
+++ b/ufl/algorithms/expand_compounds.py
@@ -2,7 +2,7 @@
 """Algorithm for expanding compound expressions into
 equivalent representations using basic operators."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -23,5 +23,6 @@ equivalent representations using basic operators."""
 
 from ufl.algorithms.apply_algebra_lowering import apply_algebra_lowering
 
+
 def expand_compounds(e):
     return apply_algebra_lowering(e)
diff --git a/ufl/algorithms/expand_indices.py b/ufl/algorithms/expand_indices.py
index 581f311..e9508f1 100644
--- a/ufl/algorithms/expand_indices.py
+++ b/ufl/algorithms/expand_indices.py
@@ -3,7 +3,7 @@
 for expanding free indices in expressions to explicit fixed
 indices only."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -27,11 +27,7 @@ from six.moves import xrange as range
 
 from ufl.log import error
 from ufl.utils.stacks import Stack, StackDict
-from ufl.assertions import ufl_assert
-from ufl.finiteelement import TensorElement
-from ufl.classes import Expr, Terminal, ListTensor, IndexSum, Indexed, FormArgument
-from ufl.tensors import as_tensor, ComponentTensor
-from ufl.permutation import compute_indices
+from ufl.classes import Terminal, ListTensor
 from ufl.constantvalue import Zero
 from ufl.core.multiindex import Index, FixedIndex, MultiIndex
 from ufl.differentiation import Grad
@@ -55,7 +51,8 @@ class IndexExpander(ReuseTransformer):
     def terminal(self, x):
         if x.ufl_shape:
             c = self.component()
-            ufl_assert(len(x.ufl_shape) == len(c), "Component size mismatch.")
+            if len(x.ufl_shape) != len(c):
+                error("Component size mismatch.")
             return x[c]
         return x
 
@@ -69,17 +66,20 @@ class IndexExpander(ReuseTransformer):
 
             # Get component
             c = self.component()
-            ufl_assert(r == len(c), "Component size mismatch.")
+            if r != len(c):
+                error("Component size mismatch.")
 
             # Map it through an eventual symmetry mapping
             s = e.symmetry()
             c = s.get(c, c)
-            ufl_assert(r == len(c), "Component size mismatch after symmetry mapping.")
+            if r != len(c):
+                error("Component size mismatch after symmetry mapping.")
 
             return x[c]
 
     def zero(self, x):
-        ufl_assert(len(x.ufl_shape) == len(self.component()), "Component size mismatch.")
+        if len(x.ufl_shape) != len(self.component()):
+            error("Component size mismatch.")
 
         s = set(x.ufl_free_indices) - set(i.count() for i in self._index2value.keys())
         if s:
@@ -91,7 +91,8 @@ class IndexExpander(ReuseTransformer):
     def scalar_value(self, x):
         if len(x.ufl_shape) != len(self.component()):
             self.print_visit_stack()
-        ufl_assert(len(x.ufl_shape) == len(self.component()), "Component size mismatch.")
+        if len(x.ufl_shape) != len(self.component()):
+            error("Component size mismatch.")
 
         s = set(x.ufl_free_indices) - set(i.count() for i in self._index2value.keys())
         if s:
@@ -99,19 +100,40 @@ class IndexExpander(ReuseTransformer):
 
         return x._ufl_class_(x.value())
 
+    def conditional(self, x):
+        c, t, f = x.ufl_operands
+
+        # Not accepting nonscalars in condition
+        if c.ufl_shape != ():
+            error("Not expecting tensor in condition.")
+
+        # Conditional may be indexed, push empty component
+        self._components.push(())
+        c = self.visit(c)
+        self._components.pop()
+
+        # Keep possibly non-scalar components for values
+        t = self.visit(t)
+        f = self.visit(f)
+
+        return self.reuse_if_possible(x, c, t, f)
+
     def division(self, x):
         a, b = x.ufl_operands
 
         # Not accepting nonscalars in division anymore
-        ufl_assert(a.ufl_shape == (), "Not expecting tensor in division.")
-        ufl_assert(self.component() == (), "Not expecting component in division.")
+        if a.ufl_shape != ():
+            error("Not expecting tensor in division.")
+        if self.component() != ():
+            error("Not expecting component in division.")
 
-        ufl_assert(b.ufl_shape == (), "Not expecting division by tensor.")
+        if b.ufl_shape != ():
+            error("Not expecting division by tensor.")
         a = self.visit(a)
 
-        #self._components.push(())
+        # self._components.push(())
         b = self.visit(b)
-        #self._components.pop()
+        # self._components.pop()
 
         return self.reuse_if_possible(x, a, b)
 
@@ -150,16 +172,16 @@ class IndexExpander(ReuseTransformer):
         self._components.push(self._multi_index_values(ii))
 
         # Hide index values (doing this is not correct behaviour)
-        #for i in ii:
-        #    if isinstance(i, Index):
-        #        self._index2value.push(i, None)
+        # for i in ii:
+        #     if isinstance(i, Index):
+        #         self._index2value.push(i, None)
 
         result = self.visit(A)
 
         # Un-hide index values
-        #for i in ii:
-        #    if isinstance(i, Index):
-        #        self._index2value.pop()
+        # for i in ii:
+        #     if isinstance(i, Index):
+        #         self._index2value.pop()
 
         # Reset component
         self._components.pop()
@@ -169,11 +191,13 @@ class IndexExpander(ReuseTransformer):
         # This function evaluates the tensor expression
         # with indices equal to the current component tuple
         expression, indices = x.ufl_operands
-        ufl_assert(expression.ufl_shape == (), "Expecting scalar base expression.")
+        if expression.ufl_shape != ():
+            error("Expecting scalar base expression.")
 
         # Update index map with component tuple values
         comp = self.component()
-        ufl_assert(len(indices) == len(comp), "Index/component mismatch.")
+        if len(indices) != len(comp):
+            error("Index/component mismatch.")
         for i, v in zip(indices.indices(), comp):
             self._index2value.push(i, v)
         self._components.push(())
@@ -200,8 +224,8 @@ class IndexExpander(ReuseTransformer):
 
     def grad(self, x):
         f, = x.ufl_operands
-        ufl_assert(isinstance(f, (Terminal, Grad)),
-                   "Expecting expand_derivatives to have been applied.")
+        if not isinstance(f, (Terminal, Grad)):
+            error("Expecting expand_derivatives to have been applied.")
         # No need to visit child as long as it is on the form [Grad]([Grad](terminal))
         return x[self.component()]
 
@@ -215,5 +239,5 @@ def purge_list_tensors(expr):
     expressions to use their components directly.
     Will usually increase the size of the expression."""
     if any(isinstance(subexpr, ListTensor) for subexpr in unique_pre_traversal(expr)):
-        return expand_indices(expr) # TODO: Only expand what's necessary to get rid of list tensors
+        return expand_indices(expr)  # TODO: Only expand what's necessary to get rid of list tensors
     return expr
diff --git a/ufl/algorithms/formdata.py b/ufl/algorithms/formdata.py
index d77cb2e..445fb3f 100644
--- a/ufl/algorithms/formdata.py
+++ b/ufl/algorithms/formdata.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """FormData class easy for collecting of various data about a form."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,9 +20,11 @@
 #
 # Modified by Anders Logg, 2008.
 
+#import six
 from ufl.utils.formatting import lstr, tstr, estr
-from ufl.assertions import ufl_assert
 
+
+# @six.python_2_unicode_compatible
 class FormData(object):
     """
     Class collecting various information extracted from a Form by
@@ -32,27 +34,33 @@ class FormData(object):
     def __init__(self):
         "Create empty form data for given form."
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         "Return formatted summary of form data"
         types = sorted(self.max_subdomain_ids.keys())
         geometry = (
-                   ("Geometric dimension", self.geometric_dimension),
-                   )
+            ("Geometric dimension", self.geometric_dimension),
+        )
         subdomains = tuple(("Number of %s subdomains" % integral_type,
                             self.max_subdomain_ids[integral_type]) for integral_type in types)
         functions = (
-                # Arguments
-                ("Rank",                               self.rank),
-                ("Arguments",                          lstr(self.original_form.arguments())),
-                # Coefficients
-                ("Number of coefficients",             self.num_coefficients),
-                ("Coefficients",                       lstr(self.reduced_coefficients)),
-                # Elements
-                ("Unique elements",                    estr(self.unique_elements)),
-                ("Unique sub elements",                estr(self.unique_sub_elements)),
-                    )
+            # Arguments
+            ("Rank", self.rank),
+            ("Arguments", lstr(self.original_form.arguments())),
+            # Coefficients
+            ("Number of coefficients", self.num_coefficients),
+            ("Coefficients", lstr(self.reduced_coefficients)),
+            # Elements
+            ("Unique elements", estr(self.unique_elements)),
+            ("Unique sub elements", estr(self.unique_sub_elements)),
+        )
         return tstr(geometry + subdomains + functions)
 
+
+# @six.python_2_unicode_compatible
 class ExprData(object):
     """
     Class collecting various information extracted from a Expr by
@@ -62,20 +70,23 @@ class ExprData(object):
     def __init__(self):
         "Create empty expr data for given expr."
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         "Return formatted summary of expr data"
-        return tstr((("Name",                               self.name),
-                     ("Cell",                               self.cell),
-                     ("Topological dimension",              self.topological_dimension),
-                     ("Geometric dimension",                self.geometric_dimension),
-                     ("Rank",                               self.rank),
-                     ("Number of coefficients",             self.num_coefficients),
-                     ("Arguments",                          lstr(self.arguments)),
-                     ("Coefficients",                       lstr(self.coefficients)),
-                     ("Argument names",                     lstr(self.argument_names)),
-                     ("Coefficient names",                  lstr(self.coefficient_names)),
-                     ("Unique elements",                    estr(self.unique_elements)),
-                     ("Unique sub elements",                estr(self.unique_sub_elements)),
+        return tstr((("Name", self.name),
+                     ("Cell", self.cell),
+                     ("Topological dimension", self.topological_dimension),
+                     ("Geometric dimension", self.geometric_dimension),
+                     ("Rank", self.rank),
+                     ("Number of coefficients", self.num_coefficients),
+                     ("Arguments", lstr(self.arguments)),
+                     ("Coefficients", lstr(self.coefficients)),
+                     ("Argument names", lstr(self.argument_names)),
+                     ("Coefficient names", lstr(self.coefficient_names)),
+                     ("Unique elements", estr(self.unique_elements)),
+                     ("Unique sub elements", estr(self.unique_sub_elements)),
                      # FIXME DOMAINS what is "the domain(s)" for an expression?
-                     ("Domains",                            self.domains),
-                     ))
+                     ("Domains", self.domains), ))
diff --git a/ufl/algorithms/formfiles.py b/ufl/algorithms/formfiles.py
index 21d3d7f..36b8dd1 100644
--- a/ufl/algorithms/formfiles.py
+++ b/ufl/algorithms/formfiles.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """A collection of utility algorithms for handling UFL files."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,23 +21,26 @@
 # Modified by Anders Logg, 2008-2009.
 # Modified by Marie E. Rognes, 2011.
 
+import six
+import io
 import os
 import re
+import ufl
 from ufl.log import error, warning
 from ufl.utils.sorting import sorted_by_key
-from ufl.assertions import ufl_assert
 from ufl.form import Form
 from ufl.finiteelement import FiniteElementBase
 from ufl.core.expr import Expr
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
 
+
 class FileData(object):
     def __init__(self):
-        self.elements     = []
+        self.elements = []
         self.coefficients = []
-        self.expressions  = []
-        self.forms        = []
+        self.expressions = []
+        self.forms = []
         self.object_names = {}
         self.object_by_name = {}
         self.reserved_objects = {}
@@ -47,28 +50,53 @@ class FileData(object):
                     self.object_names or self.object_by_name or self.reserved_objects)
     __nonzero__ = __bool__
 
-infostring = """An exception occured during evaluation of form file.
-To help you find the location of the error, a temporary script
-'%s'
-has been created and will now be executed with debug output enabled:"""
 
-def replace_include_statements(code):
+def read_lines_decoded(fn):
+    r = re.compile(b".*coding: *([^ ]+)")
+    if six.PY3:
+        def match(line):
+            return r.match(line, re.ASCII)
+    else:
+        def match(line):
+            return r.match(line)
+
+    # First read lines as bytes
+    with io.open(fn, "rb") as f:
+        lines = f.readlines()
+
+    # Check for coding: in the first two lines
+    for i in range(min(2, len(lines))):
+        m = match(lines[i])
+        if m:
+            encoding, = m.groups()
+            # Drop encoding line
+            lines = lines[:i] + lines[i+1:]
+            break
+    else:
+        # Default to utf-8 (works for ascii files
+        # as well, default for python files in py3)
+        encoding = "utf-8"
+
+    # Decode all lines
+    lines = [line.decode(encoding=encoding) for line in lines]
+    return lines
+
+
+def replace_include_statements(lines):
     "Replace '#include foo.ufl' statements with contents of foo.ufl."
-    if "#include" in code:
-        lines = code.split("\n")
-        newlines = []
-        regexp = re.compile(r"^#include (.*)$")
-        for l in lines:
-            m = regexp.search(l)
-            if m:
-                fn = m.groups()[0]
-                newlines.append("# --- begin %s" % fn)
-                newlines.extend(open(fn).readlines())
-                newlines.append("# --- end %s" % fn)
-            else:
-                newlines.append(l)
-        return "\n".join(l.rstrip() for l in newlines)
-    return code
+    r = re.compile(r"^#include (.*)$")
+    newlines = []
+    for l in lines:
+        m = r.search(l)
+        if m:
+            fn = m.groups()[0]
+            newlines.append("# --- begin %s\n" % fn)
+            newlines.extend(read_lines_decoded(fn))
+            newlines.append("# --- end %s\n" % fn)
+        else:
+            newlines.append(l)
+    return newlines
+
 
 def read_ufl_file(filename):
     "Read a .ufl file, handling file extension, file existance, and #include replacement."
@@ -76,29 +104,36 @@ def read_ufl_file(filename):
         filename = filename + ".ufl"
     if not os.path.exists(filename):
         error("File '%s' doesn't exist." % filename)
-    with open(filename) as f:
-        code = replace_include_statements(f.read())
+    lines = read_lines_decoded(filename)
+    lines = replace_include_statements(lines)
+    code = "".join(lines)
     return code
 
+
+infostring = """\
+An exception occured during evaluation of .ufl file.
+If you need to debug it as a python script, rename it to .py
+and add the lines
+
+    from ufl import *
+    set_level(DEBUG)
+
+at the top then run with python.
+"""
+
+
 def execute_ufl_code(uflcode, filename):
     # Execute code
     namespace = {}
+    namespace.update(vars(ufl))
     try:
-        pycode = "# -*- coding: utf-8 -*-\nfrom ufl import *\n" + uflcode
-        exec(pycode, namespace)
-    except:
-        # Dump python code for debugging if this fails
-        basename = os.path.splitext(os.path.basename(filename))[0]
-        basename = "%s_debug" % basename
-        pyname = "%s.py" % basename
-        pycode = "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nfrom ufl import *\nset_level(DEBUG)\n" + uflcode
-        with open(pyname, "w") as f:
-            f.write(pycode)
-        warning(infostring % pyname)
-        m = __import__(basename)
-        error("An error occured, aborting load_forms.")
+        exec(uflcode, namespace)
+    except Exception as e:
+        warning(infostring)
+        raise e
     return namespace
 
+
 def interpret_ufl_namespace(namespace):
     "Takes a namespace dict from an executed ufl file and converts it to a FileData object."
     # Object to hold all returned data
@@ -110,7 +145,7 @@ def interpret_ufl_namespace(namespace):
     # and not just between objects with different values.
     for name, value in sorted_by_key(namespace):
         # Store objects by reserved name OR instance id
-        reserved_names = ("unknown",) # Currently only one reserved name
+        reserved_names = ("unknown",)  # Currently only one reserved name
         if name in reserved_names:
             # Store objects with reserved names
             ufd.reserved_objects[name] = value
@@ -118,14 +153,16 @@ def interpret_ufl_namespace(namespace):
             ufd.object_names[name] = value
             ufd.object_by_name[name] = value
         elif isinstance(value, (FiniteElementBase, Coefficient, Argument, Form, Expr)):
-            # Store instance <-> name mappings for important objects without a reserved name
+            # Store instance <-> name mappings for important objects
+            # without a reserved name
             ufd.object_names[id(value)] = name
             ufd.object_by_name[name] = value
 
     # Get list of exported forms
     forms = namespace.get("forms")
     if forms is None:
-        # Get forms from object_by_name, which has already mapped tuple->Form where needed
+        # Get forms from object_by_name, which has already mapped
+        # tuple->Form where needed
         def get_form(name):
             form = ufd.object_by_name.get(name)
             return form if isinstance(form, Form) else None
@@ -143,10 +180,10 @@ def interpret_ufl_namespace(namespace):
     ufd.forms = forms
 
     # Validate types
-    ufl_assert(isinstance(ufd.forms, (list, tuple)),
-        "Expecting 'forms' to be a list or tuple, not '%s'." % type(ufd.forms))
-    ufl_assert(all(isinstance(a, Form) for a in ufd.forms),
-        "Expecting 'forms' to be a list of Form instances.")
+    if not isinstance(ufd.forms, (list, tuple)):
+        error("Expecting 'forms' to be a list or tuple, not '%s'." % type(ufd.forms))
+    if not all(isinstance(a, Form) for a in ufd.forms):
+        error("Expecting 'forms' to be a list of Form instances.")
 
     # Get list of exported elements
     elements = namespace.get("elements")
@@ -156,37 +193,38 @@ def interpret_ufl_namespace(namespace):
     ufd.elements = elements
 
     # Validate types
-    ufl_assert(isinstance(ufd.elements,  (list, tuple)),
-        "Expecting 'elements' to be a list or tuple, not '%s'." % type(ufd.elements))
-    ufl_assert(all(isinstance(e, FiniteElementBase) for e in ufd.elements),
-        "Expecting 'elements' to be a list of FiniteElementBase instances.")
+    if not isinstance(ufd.elements, (list, tuple)):
+        error("Expecting 'elements' to be a list or tuple, not '%s'." % type(ufd.elements))
+    if not all(isinstance(e, FiniteElementBase) for e in ufd.elements):
+        error("Expecting 'elements' to be a list of FiniteElementBase instances.")
 
     # Get list of exported coefficients
-    # TODO: Temporarily letting 'coefficients' override 'functions', but allow 'functions' for compatibility
+    # TODO: Temporarily letting 'coefficients' override 'functions',
+    # but allow 'functions' for compatibility
     functions = namespace.get("functions", [])
     if functions:
         warning("Deprecation warning: Rename 'functions' to 'coefficients' to export coefficients.")
     ufd.coefficients = namespace.get("coefficients", functions)
-    #ufd.coefficients = namespace.get("coefficients", [])
 
     # Validate types
-    ufl_assert(isinstance(ufd.coefficients, (list, tuple)),
-        "Expecting 'coefficients' to be a list or tuple, not '%s'." % type(ufd.coefficients))
-    ufl_assert(all(isinstance(e, Coefficient) for e in ufd.coefficients),
-        "Expecting 'coefficients' to be a list of Coefficient instances.")
+    if not isinstance(ufd.coefficients, (list, tuple)):
+        error("Expecting 'coefficients' to be a list or tuple, not '%s'." % type(ufd.coefficients))
+    if not all(isinstance(e, Coefficient) for e in ufd.coefficients):
+        error("Expecting 'coefficients' to be a list of Coefficient instances.")
 
     # Get list of exported expressions
     ufd.expressions = namespace.get("expressions", [])
 
     # Validate types
-    ufl_assert(isinstance(ufd.expressions, (list, tuple)),
-        "Expecting 'expressions' to be a list or tuple, not '%s'." % type(ufd.expressions))
-    ufl_assert(all(isinstance(e, Expr) for e in ufd.expressions),
-        "Expecting 'expressions' to be a list of Expr instances.")
+    if not isinstance(ufd.expressions, (list, tuple)):
+        error("Expecting 'expressions' to be a list or tuple, not '%s'." % type(ufd.expressions))
+    if not all(isinstance(e, Expr) for e in ufd.expressions):
+        error("Expecting 'expressions' to be a list of Expr instances.")
 
     # Return file data
     return ufd
 
+
 def load_ufl_file(filename):
     "Load a .ufl file with elements, coefficients and forms."
     # Read code from file and execute it
@@ -194,6 +232,7 @@ def load_ufl_file(filename):
     namespace = execute_ufl_code(uflcode, filename)
     return interpret_ufl_namespace(namespace)
 
+
 def load_forms(filename):
     "Return a list of all forms in a file."
     ufd = load_ufl_file(filename)
diff --git a/ufl/algorithms/formsplitter.py b/ufl/algorithms/formsplitter.py
old mode 100755
new mode 100644
index 790ef70..d0747e0
--- a/ufl/algorithms/formsplitter.py
+++ b/ufl/algorithms/formsplitter.py
@@ -25,6 +25,7 @@ from ufl.tensors import as_vector
 from ufl.argument import Argument
 from ufl.functionspace import FunctionSpace
 
+
 class FormSplitter(MultiFunction):
 
     def split(self, form, ix, iy=0):
@@ -47,7 +48,7 @@ class FormSplitter(MultiFunction):
             Q_i = FunctionSpace(dom, sub_elem)
             a = Argument(Q_i, obj.number(), part=obj.part())
 
-            indices =[()]
+            indices = [()]
             for m in a.ufl_shape:
                 indices = [(k + (j,)) for k in indices for j in range(m)]
 
@@ -63,6 +64,7 @@ class FormSplitter(MultiFunction):
 
     expr = MultiFunction.reuse_if_untouched
 
+
 def block_split(form, ix, iy=0):
     fs = FormSplitter()
     return fs.split(form, ix, iy)
diff --git a/ufl/algorithms/formtransformations.py b/ufl/algorithms/formtransformations.py
index 81caa5b..24234b0 100644
--- a/ufl/algorithms/formtransformations.py
+++ b/ufl/algorithms/formtransformations.py
@@ -2,7 +2,7 @@
 """This module defines utilities for transforming
 complete Forms into new related Forms."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -26,15 +26,13 @@ complete Forms into new related Forms."""
 from six import iteritems
 from six.moves import xrange as range
 
-from ufl.utils.sequences import product
 from ufl.log import error, warning, debug
-from ufl.assertions import ufl_assert
 
 # All classes:
+from ufl.core.expr import ufl_err_str
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
 from ufl.constantvalue import Zero
-from ufl.algebra import Sum
 
 # Other algorithms:
 from ufl.algorithms.map_integrands import map_integrands
@@ -73,7 +71,7 @@ class PartExtracter(Transformer):
         """The default is a nonlinear operator not accepting any
         Arguments among its children."""
         if _expr_has_terminal_types(x, Argument):
-            error("Found Argument in %s, this is an invalid expression." % repr(x))
+            error("Found Argument in %s, this is an invalid expression." % ufl_err_str(x))
         return (x, set())
 
     # Terminals that are not Variables or Arguments behave as default
@@ -165,7 +163,7 @@ class PartExtracter(Transformer):
 
         # 3. Return the terms that provide the biggest set
         most_provided = frozenset()
-        for (provideds, parts) in iteritems(parts_that_provide): # TODO: Just sort instead?
+        for (provideds, parts) in iteritems(parts_that_provide):  # TODO: Just sort instead?
 
             # Throw error if size of sets are equal (and not zero)
             if len(provideds) == len(most_provided) and len(most_provided):
@@ -221,7 +219,7 @@ class PartExtracter(Transformer):
 
         # Check for Arguments in the denominator
         if _expr_has_terminal_types(denominator, Argument):
-            error("Found Argument in denominator of %s , this is an invalid expression." % repr(x))
+            error("Found Argument in denominator of %s , this is an invalid expression." % ufl_err_str(x))
 
         # Visit numerator
         numerator_parts, provides = self.visit(numerator)
@@ -312,6 +310,7 @@ class PartExtracter(Transformer):
 
         return (x, most_provides)
 
+
 def compute_form_with_arity(form, arity, arguments=None):
     """Compute parts of form of given arity."""
 
@@ -333,6 +332,7 @@ def compute_form_with_arity(form, arity, arguments=None):
     # any sense anyway.
     sub_arguments = set(arguments[:arity])
     pe = PartExtracter(sub_arguments)
+
     def _transform(e):
         e, provides = pe.visit(e)
         if provides == sub_arguments:
@@ -340,9 +340,9 @@ def compute_form_with_arity(form, arity, arguments=None):
         return Zero()
     return map_integrands(_transform, form)
 
+
 def compute_form_arities(form):
     """Return set of arities of terms present in form."""
-    #ufl_assert(form.is_preprocessed(), "Assuming a preprocessed form.")
 
     # Extract all arguments present in form
     arguments = form.arguments()
@@ -363,6 +363,7 @@ def compute_form_arities(form):
 
     return arities
 
+
 def compute_form_lhs(form):
     """Compute the left hand side of a form.
 
@@ -373,6 +374,7 @@ def compute_form_lhs(form):
     """
     return compute_form_with_arity(form, 2)
 
+
 def compute_form_rhs(form):
     """Compute the right hand side of a form.
 
@@ -383,6 +385,7 @@ def compute_form_rhs(form):
     """
     return -compute_form_with_arity(form, 1)
 
+
 def compute_form_functional(form):
     """Compute the functional part of a form, that
     is the terms independent of Arguments.
@@ -390,6 +393,7 @@ def compute_form_functional(form):
     (Used for testing, not sure if it's useful for anything?)"""
     return compute_form_with_arity(form, 0)
 
+
 def compute_form_action(form, coefficient):
     """Compute the action of a form on a Coefficient.
 
@@ -416,7 +420,8 @@ def compute_form_action(form, coefficient):
         coefficient = Coefficient(fs)
     elif coefficient.ufl_function_space() != fs:
         debug("Computing action of form on a coefficient in a different function space.")
-    return replace(form, { u: coefficient })
+    return replace(form, {u: coefficient})
+
 
 def compute_energy_norm(form, coefficient):
     """Compute the a-norm of a Coefficient given a form a.
@@ -433,18 +438,21 @@ def compute_energy_norm(form, coefficient):
     if set(parts) - {None}:
         error("compute_energy_norm cannot handle parts.")
 
-    ufl_assert(len(arguments) == 2, "Expecting bilinear form.")
+    if len(arguments) != 2:
+        error("Expecting bilinear form.")
     v, u = arguments
-    e = u.ufl_function_space()
-    e2 = v.ufl_function_space()
-    ufl_assert(e == e2, "Expecting equal finite elements for test and trial functions, got '%s' and '%s'." % (str(e), str(e2)))
+    U = u.ufl_function_space()
+    V = v.ufl_function_space()
+    if U != V:
+        error("Expecting equal finite elements for test and trial functions, got '%s' and '%s'." % (U, V))
     if coefficient is None:
-        coefficient = Coefficient(e)
+        coefficient = Coefficient(V)
     else:
-        ufl_assert(coefficient.ufl_function_space() == e,
-            "Trying to compute action of form on a "
-            "coefficient in an incompatible element space.")
-    return replace(form, { u: coefficient, v: coefficient })
+        if coefficient.ufl_function_space() != U:
+            error("Trying to compute action of form on a "
+                  "coefficient in an incompatible element space.")
+    return replace(form, {u: coefficient, v: coefficient})
+
 
 def compute_form_adjoint(form, reordered_arguments=None):
     """Compute the adjoint of a bilinear form.
@@ -458,28 +466,32 @@ def compute_form_adjoint(form, reordered_arguments=None):
     if set(parts) - {None}:
         error("compute_form_adjoint cannot handle parts.")
 
-    ufl_assert(len(arguments) == 2, "Expecting bilinear form.")
+    if len(arguments) != 2:
+        error("Expecting bilinear form.")
 
     v, u = arguments
-    ufl_assert(v.number() < u.number(), "Mistaken assumption in code!")
+    if v.number() >= u.number():
+        error("Mistaken assumption in code!")
 
     if reordered_arguments is None:
-        reordered_u = Argument(u.ufl_function_space(), number=v.number(), part=v.part())
-        reordered_v = Argument(v.ufl_function_space(), number=u.number(), part=u.part())
+        reordered_u = Argument(u.ufl_function_space(), number=v.number(),
+                               part=v.part())
+        reordered_v = Argument(v.ufl_function_space(), number=u.number(),
+                               part=u.part())
     else:
         reordered_u, reordered_v = reordered_arguments
 
-    ufl_assert(reordered_u.number() < reordered_v.number(),
-               "Ordering of new arguments is the same as the old arguments!")
+    if reordered_u.number() >= reordered_v.number():
+        error("Ordering of new arguments is the same as the old arguments!")
 
-    ufl_assert(reordered_u.part() == v.part(),
-               "Ordering of new arguments is the same as the old arguments!")
-    ufl_assert(reordered_v.part() == u.part(),
-               "Ordering of new arguments is the same as the old arguments!")
+    if reordered_u.part() != v.part():
+        error("Ordering of new arguments is the same as the old arguments!")
+    if reordered_v.part() != u.part():
+        error("Ordering of new arguments is the same as the old arguments!")
 
-    ufl_assert(reordered_u.ufl_function_space() == u.ufl_function_space(),
-               "Element mismatch between new and old arguments (trial functions).")
-    ufl_assert(reordered_v.ufl_function_space() == v.ufl_function_space(),
-               "Element mismatch between new and old arguments (test functions).")
+    if reordered_u.ufl_function_space() != u.ufl_function_space():
+        error("Element mismatch between new and old arguments (trial functions).")
+    if reordered_v.ufl_function_space() != v.ufl_function_space():
+        error("Element mismatch between new and old arguments (test functions).")
 
     return replace(form, {v: reordered_v, u: reordered_u})
diff --git a/ufl/algorithms/forward_ad.py b/ufl/algorithms/forward_ad.py
deleted file mode 100644
index 7abf1a0..0000000
--- a/ufl/algorithms/forward_ad.py
+++ /dev/null
@@ -1,1018 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Forward mode AD implementation."""
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-#
-# Modified by Anders Logg, 2009.
-# Modified by Garth N. Wells, 2010.
-# Modified by Kristian B. Oelgaard, 2011
-# Modified by Jan Blechta, 2012.
-
-from six.moves import xrange as range
-from six.moves import zip
-
-from math import pi
-from ufl.log import error, warning, debug
-from ufl.assertions import ufl_assert
-from ufl.utils.sequences import unzip
-from ufl.utils.dicts import subdict
-from ufl.utils.formatting import lstr
-
-# All classes:
-from ufl.core.terminal import Terminal
-from ufl.constantvalue import ConstantValue, Zero, IntValue, Identity, is_true_ufl_scalar, is_ufl_scalar
-from ufl.variable import Variable
-from ufl.coefficient import Coefficient, FormArgument
-from ufl.core.multiindex import MultiIndex, Index, FixedIndex, indices
-from ufl.indexed import Indexed
-from ufl.indexsum import IndexSum
-from ufl.tensors import ListTensor, ComponentTensor, as_tensor, as_scalar, unit_indexed_tensor, unwrap_list_tensor
-from ufl.algebra import Sum, Product, Division, Power, Abs
-from ufl.tensoralgebra import Transposed, Outer, Inner, Dot, Cross, Trace, Determinant, Inverse, Deviatoric, Cofactor
-from ufl.mathfunctions import MathFunction, Sqrt, Exp, Ln, Cos, Sin, Tan, Acos, Asin, Atan, Atan2, Erf, BesselJ, BesselY, BesselI, BesselK
-from ufl.restriction import Restricted, PositiveRestricted, NegativeRestricted
-from ufl.differentiation import Derivative, CoefficientDerivative, VariableDerivative, Grad
-from ufl.conditional import EQ, NE, LE, GE, LT, GT, Conditional
-from ufl.exprcontainers import ExprList, ExprMapping
-from ufl.operators import (dot, inner, outer, lt, eq, conditional, sign,
-    sqrt, exp, ln, cos, sin, tan, cosh, sinh, tanh, acos, asin, atan, atan_2,
-    erf, bessel_J, bessel_Y, bessel_I, bessel_K,
-    cell_avg, facet_avg)
-from ufl.algorithms.transformer import Transformer
-from ufl.domain import find_geometric_dimension
-from ufl.checks import is_cellwise_constant
-
-
-class ForwardAD(Transformer):
-    def __init__(self, var_shape, cache=None):
-        Transformer.__init__(self)
-        self._var_shape = var_shape
-        self._variable_cache = {} if cache is None else cache
-
-    def _debug_visit(self, o):
-        "Debugging hook, enable this by renaming to 'visit'."
-        r = Transformer.visit(self, o)
-        f, df = r
-        if f is not o:
-            debug("In ForwardAD.visit, didn't get back o:")
-            debug("  o:  %s" % str(o))
-            debug("  f:  %s" % str(f))
-            debug("  df: %s" % str(df))
-        fi_diff = set(f.ufl_free_indices) ^ set(df.ufl_free_indices)
-        if fi_diff:
-            debug("In ForwardAD.visit, got free indices diff:")
-            debug("  o:  %s" % str(o))
-            debug("  f:  %s" % str(f))
-            debug("  df: %s" % str(df))
-            debug("  f.fi():  %s" % lstr(f.ufl_free_indices))
-            debug("  df.fi(): %s" % lstr(df.ufl_free_indices))
-            debug("  fi_diff: %s" % str(fi_diff))
-        return r
-
-    def _make_zero_diff(self, o):
-        # Define a zero with the right shape and indices
-        return Zero(o.ufl_shape + self._var_shape, o.ufl_free_indices, o.ufl_index_dimensions)
-
-    # --- Default rules
-
-    def expr(self, o):
-        error("Missing ForwardAD handler for type %s" % str(type(o)))
-
-    def terminal(self, o):
-        """Terminal objects are assumed independent of the differentiation
-        variable by default, and simply 'lifted' to the pair (o, 0).
-        Depending on the context, override this with custom rules for
-        non-zero derivatives."""
-        fp = self._make_zero_diff(o)
-        return (o, fp)
-
-    def variable(self, o):
-        """Variable objects are just 'labels', so by default the derivative
-        of a variable is the derivative of its referenced expression."""
-        # Check variable cache to reuse previously transformed variable if possible
-        e, l = o.ufl_operands
-        r = self._variable_cache.get(l) # cache contains (v, vp) tuple
-        if r is not None:
-            return r
-
-        # Visit the expression our variable represents
-        e2, vp = self.visit(e)
-
-        # Recreate Variable (with same label) only if necessary
-        v = self.reuse_if_possible(o, e2, l)
-
-        # Cache and return (v, vp) tuple
-        r = (v, vp)
-        self._variable_cache[l] = r
-        return r
-
-    # --- Indexing and component handling
-
-    def multi_index(self, o):
-        return (o, None) # oprime here should never be used, this might even not be called?
-
-    def indexed(self, o):
-        A, jj = o.ufl_operands
-        A2, Ap = self.visit(A)
-        o = self.reuse_if_possible(o, A2, jj)
-
-        if isinstance(Ap, Zero):
-            op = self._make_zero_diff(o)
-        else:
-            r = len(Ap.ufl_shape) - len(jj)
-            if r:
-                ii = indices(r)
-                op = Indexed(Ap, MultiIndex(jj.indices() + ii))
-                op = as_tensor(op, ii)
-            else:
-                op = Indexed(Ap, jj)
-        return (o, op)
-
-    def list_tensor(self, o, *ops):
-        ops, dops = unzip(ops)
-        o = self.reuse_if_possible(o, *ops)
-        op = ListTensor(*dops)
-        return (o, op)
-
-    def component_tensor(self, o):
-        A, ii = o.ufl_operands
-        A, Ap = self.visit(A)
-        o = self.reuse_if_possible(o, A, ii)
-
-        if isinstance(Ap, Zero):
-            op = self._make_zero_diff(o)
-        else:
-            Ap, jj = as_scalar(Ap)
-            op = as_tensor(Ap, ii.indices() + jj)
-        return (o, op)
-
-    # --- Algebra operators
-
-    def index_sum(self, o):
-        A, i = o.ufl_operands
-        A2, Ap = self.visit(A)
-        o = self.reuse_if_possible(o, A2, i)
-        op = IndexSum(Ap, i)
-        return (o, op)
-
-    def sum(self, o, *ops):
-        ops, opsp = unzip(ops)
-        o2 = self.reuse_if_possible(o, *ops)
-        op = sum(opsp[1:], opsp[0])
-        return (o2, op)
-
-    def product(self, o, *ops):
-        # Start with a zero with the right shape and indices
-        fp = self._make_zero_diff(o)
-        # Get operands and their derivatives
-        ops2, dops2 = unzip(ops)
-        o = self.reuse_if_possible(o, *ops2)
-        for i in range(len(ops)):
-            # Get scalar representation of differentiated value of operand i
-            dop = dops2[i]
-            dop, ii = as_scalar(dop)
-            # Replace operand i with its differentiated value in product
-            fpoperands = ops2[:i] + [dop] + ops2[i+1:]
-            p = Product(*fpoperands)
-            # Wrap product in tensor again
-            if ii:
-                p = as_tensor(p, ii)
-            # Accumulate terms
-            fp += p
-        return (o, fp)
-
-    def division(self, o, a, b):
-        f, fp = a
-        g, gp = b
-        o = self.reuse_if_possible(o, f, g)
-
-        ufl_assert(is_ufl_scalar(f), "Not expecting nonscalar nominator")
-        ufl_assert(is_true_ufl_scalar(g), "Not expecting nonscalar denominator")
-
-        #do_df = 1/g
-        #do_dg = -h/g
-        #op = do_df*fp + do_df*gp
-        #op = (fp - o*gp) / g
-
-        # Get o and gp as scalars, multiply, then wrap as a tensor again
-        so, oi = as_scalar(o)
-        sgp, gi = as_scalar(gp)
-        o_gp = so*sgp
-        if oi or gi:
-            o_gp = as_tensor(o_gp, oi + gi)
-        op = (fp - o_gp) / g
-
-        return (o, op)
-
-    def power(self, o, a, b):
-        f, fp = a
-        g, gp = b
-
-        # Debugging prints, should never happen:
-        if not is_true_ufl_scalar(f):
-            print(":"*80)
-            print("f =", str(f))
-            print("g =", str(g))
-            print(":"*80)
-        ufl_assert(is_true_ufl_scalar(f), "Expecting scalar expression f in f**g.")
-        ufl_assert(is_true_ufl_scalar(g), "Expecting scalar expression g in f**g.")
-
-        # Derivation of the general case: o = f(x)**g(x)
-        #
-        #do_df = g * f**(g-1)
-        #do_dg = ln(f) * f**g
-        #op = do_df*fp + do_dg*gp
-        #
-        #do_df = o * g / f # f**g * g / f
-        #do_dg = ln(f) * o
-        #op = do_df*fp + do_dg*gp
-
-        # Got two possible alternatives here:
-        if True: # This version looks better.
-            # Rewriting o as f*f**(g-1) we can do:
-            f_g_m1 = f**(g-1)
-            op = f_g_m1*(fp*g + f*ln(f)*gp)
-            # In this case we can rewrite o using new subexpression
-            o = f*f_g_m1
-        else:
-            # Pulling o out gives:
-            op = o*(fp*g/f + ln(f)*gp)
-            # This produces expressions like (1/w)*w**5 instead of w**4
-            # If we do this, we reuse o
-            o = self.reuse_if_possible(o, f, g)
-
-        return (o, op)
-
-    def abs(self, o, a):
-        f, fprime = a
-        o = self.reuse_if_possible(o, f)
-        #oprime = conditional(eq(f, 0), 0, Product(sign(f), fprime))
-        oprime = sign(f)*fprime
-        return (o, oprime)
-
-    # --- Mathfunctions
-
-    def math_function(self, o, a):
-        if hasattr(o, 'derivative'): # FIXME: Introduce a UserOperator type instead of this hack
-            f, fp = a
-            o = self.reuse_if_possible(o, f)
-            op = fp * o.derivative()
-            return (o, op)
-        error("Unknown math function.")
-
-    def sqrt(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp / (2*o)
-        return (o, op)
-
-    def exp(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp*o
-        return (o, op)
-
-    def ln(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        ufl_assert(not isinstance(f, Zero), "Division by zero.")
-        return (o, fp/f)
-
-    def cos(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = -fp*sin(f)
-        return (o, op)
-
-    def sin(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp*cos(f)
-        return (o, op)
-
-    def tan(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp*2.0/(cos(2.0*f) + 1.0)
-        return (o, op)
-
-    def cosh(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp*sinh(f)
-        return (o, op)
-
-    def sinh(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp*cosh(f)
-        return (o, op)
-
-    def tanh(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        def sech(y):
-            return (2.0*cosh(y)) / (cosh(2.0*y) + 1.0)
-        op = fp*sech(f)**2
-        return (o, op)
-
-    def acos(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = -fp/sqrt(1.0 - f**2)
-        return (o, op)
-
-    def asin(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp/sqrt(1.0 - f**2)
-        return (o, op)
-
-    def atan(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp/(1.0 + f**2)
-        return (o, op)
-
-    def atan_2(self, o, a, b):
-        f, fp = a
-        g, gp = b
-        o = self.reuse_if_possible(o, f, g)
-        op = (g*fp-f*gp)/(f**2+g**2)
-        return (o, op)
-
-    def erf(self, o, a):
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        op = fp*(2.0/sqrt(pi)*exp(-f**2))
-        return (o, op)
-
-    def bessel_j(self, o, nu, x):
-        nu, dummy = nu
-        if not (dummy is None or isinstance(dummy, Zero)):
-            error("Differentiation of bessel function w.r.t. nu is not supported.")
-        f, fp = x
-        o = self.reuse_if_possible(o, nu, f)
-        if isinstance(nu, Zero):
-            op = -bessel_J(1, f)
-        else:
-            op = 0.5 * (bessel_J(nu-1, f) - bessel_J(nu+1, f))
-        return (o, op*fp)
-
-    def bessel_y(self, o, nu, x):
-        nu, dummy = nu
-        if not (dummy is None or isinstance(dummy, Zero)):
-            error("Differentiation of bessel function w.r.t. nu is not supported.")
-        f, fp = x
-        o = self.reuse_if_possible(o, nu, f)
-        if isinstance(nu, Zero):
-            op = -bessel_Y(1, f)
-        else:
-            op = 0.5 * (bessel_Y(nu-1, f) - bessel_Y(nu+1, f))
-        return (o, op*fp)
-
-    def bessel_i(self, o, nu, x):
-        nu, dummy = nu
-        if not (dummy is None or isinstance(dummy, Zero)):
-            error("Differentiation of bessel function w.r.t. nu is not supported.")
-        f, fp = x
-        o = self.reuse_if_possible(o, nu, f)
-        if isinstance(nu, Zero):
-            op = bessel_I(1, f)
-        else:
-            op = 0.5 * (bessel_I(nu-1, f) + bessel_I(nu+1, f))
-        return (o, op*fp)
-
-    def bessel_k(self, o, nu, x):
-        nu, dummy = nu
-        if not (dummy is None or isinstance(dummy, Zero)):
-            error("Differentiation of bessel function w.r.t. nu is not supported.")
-        f, fp = x
-        o = self.reuse_if_possible(o, nu, f)
-        if isinstance(nu, Zero):
-            op = -bessel_K(1, f)
-        else:
-            op = -0.5 * (bessel_K(nu-1, f) + bessel_K(nu+1, f))
-        return (o, op*fp)
-
-    # --- Restrictions
-
-    def restricted(self, o, a):
-        # Restriction and differentiation commutes.
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        if isinstance(fp, ConstantValue):
-            return (o, fp) # TODO: Necessary? Can't restriction simplify directly instead?
-        else:
-            return (o, fp(o._side)) # (f+-)' == (f')+-
-
-    def cell_avg(self, o, a):
-        # Cell average of a single function and differentiation commutes.
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        if isinstance(fp, ConstantValue):
-            return (o, fp) # TODO: Necessary? Can't CellAvg simplify directly instead?
-        else:
-            return (o, cell_avg(fp))
-
-    def facet_avg(self, o, a):
-        # Facet average of a single function and differentiation commutes.
-        f, fp = a
-        o = self.reuse_if_possible(o, f)
-        if isinstance(fp, ConstantValue):
-            return (o, fp) # TODO: Necessary? Can't FacetAvg simplify directly instead?
-        else:
-            return (o, facet_avg(fp))
-
-    # --- Conditionals
-
-    def binary_condition(self, o, l, r):
-        o = self.reuse_if_possible(o, l[0], r[0])
-        #if any(not (isinstance(op[1], Zero) or op[1] is None) for op in (l, r)):
-        #    warning("Differentiating a conditional with a condition "
-        #                "that depends on the differentiation variable."
-        #                "Assuming continuity of conditional. The condition "
-        #                "will not be differentiated.")
-        oprime = None # Shouldn't be used anywhere
-        return (o, oprime)
-
-    def not_condition(self, o, c):
-        o = self.reuse_if_possible(o, c[0])
-        #if not (isinstance(c[1], Zero) or c[1] is None):
-        #    warning("Differentiating a conditional with a condition "
-        #                "that depends on the differentiation variable."
-        #                "Assuming continuity of conditional. The condition "
-        #                "will not be differentiated.")
-        oprime = None # Shouldn't be used anywhere
-        return (o, oprime)
-
-    def conditional(self, o, c, t, f):
-        o = self.reuse_if_possible(o, c[0], t[0], f[0])
-        if isinstance(t[1], Zero) and isinstance(f[1], Zero):
-            # Assuming t[1] and f[1] have the same indices here, which should be the case
-            op = t[1]
-        else:
-            # Placing t[1],f[1] outside here to avoid getting arguments inside conditionals
-            op = conditional(c[0], 1, 0)*t[1] + conditional(c[0], 0, 1)*f[1]
-        return (o, op)
-
-    def max_value(self, o, x, y):
-        #d/dx max(f, g) =
-        # f > g: df/dx
-        # f < g: dg/dx
-        op = conditional(x[0] > y[0], x[1], y[1])
-        return (o, op)
-
-    def min_value(self, o, x, y):
-        #d/dx min(f, g) =
-        # f < g: df/dx
-        # else: dg/dx
-        op = conditional(x[0] < y[0], x[1], y[1])
-        return (o, op)
-
-    # --- Other derivatives
-
-    def derivative(self, o):
-        error("This should never occur.")
-
-    def grad(self, o):
-        error("FIXME")
-
-# TODO: Add a ReferenceGradAD ruleset
-class GradAD(ForwardAD):
-    def __init__(self, geometric_dimension, cache=None):
-        ForwardAD.__init__(self, var_shape=(geometric_dimension,), cache=cache)
-
-    def geometric_quantity(self, o):
-        "Represent grad(g) as Grad(g)."
-        # Collapse gradient of cellwise constant function to zero
-        if is_cellwise_constant(o):
-            return self.terminal(o)
-        return (o, Grad(o))
-
-    def spatial_coordinate(self, o):
-        "Gradient of x w.r.t. x is Id."
-        if not hasattr(self, '_Id'):
-            gdim = find_geometric_dimension(o)
-            self._Id = Identity(gdim)
-        return (o, self._Id)
-
-    def cell_coordinate(self, o):
-        "Gradient of X w.r.t. x is K. But I'm not sure if we want to allow this."
-        error("This has not been validated. Does it make sense to do this here?")
-        K = JacobianInverse(o.ufl_domain())
-        return (o, K)
-
-    # TODO: Implement rules for some of these types?
-
-    def facet_coordinate(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def jacobian(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def jacobian_determinant(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def jacobian_inverse(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def facet_jacobian(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def facet_jacobian_determinant(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def facet_jacobian_inverse(self, o):
-        error("Not expecting this low level type in AD.")
-
-    def argument(self, o):
-        "Represent grad(f) as Grad(f)."
-        # Collapse gradient of cellwise constant function to zero
-        # FIXME: Enable this after fixing issue#13
-        #if is_cellwise_constant(o):
-        #    return zero(...) # TODO: zero annotated with argument
-        return (o, Grad(o))
-
-    def coefficient(self, o):
-        "Represent grad(f) as Grad(f)."
-        # Collapse gradient of cellwise constant function to zero
-        if is_cellwise_constant(o):
-            return self.terminal(o)
-        return (o, Grad(o))
-
-    def grad(self, o):
-        "Represent grad(grad(f)) as Grad(Grad(f))."
-
-        # TODO: Not sure how to detect that gradient of f is cellwise constant.
-        #       Can we trust element degrees?
-        #if is_cellwise_constant(o):
-        #    return self.terminal(o)
-        # TODO: Maybe we can ask "f.has_derivatives_of_order(n)" to check
-        #       if we should make a zero here?
-        # 1) n = count number of Grads, get f
-        # 2) if not f.has_derivatives(n): return zero(...)
-
-        f, = o.ufl_operands
-        ufl_assert(isinstance(f, (Grad, Terminal)),
-                   "Expecting derivatives of child to be already expanded.")
-        return (o, Grad(o))
-
-class VariableAD(ForwardAD):
-    def __init__(self, var, cache=None):
-        ForwardAD.__init__(self, var_shape=var.ufl_shape, cache=cache)
-        ufl_assert(not var.ufl_free_indices, "Differentiation variable cannot have free indices.")
-        self._variable = var
-
-    def grad(self, o):
-        # If we hit this type, it has already been propagated
-        # to a coefficient, so it cannot depend on the variable. # FIXME: Assert this!
-        return self.terminal(o)
-
-    def _make_self_diff_identity(self, o):
-        sh = o.ufl_shape
-        res = None
-        if sh == ():
-            # Scalar dv/dv is scalar
-            return IntValue(1)
-        elif len(sh) == 1:
-            # Vector v makes dv/dv the identity matrix
-            return Identity(sh[0])
-        else:
-            # Tensor v makes dv/dv some kind of higher rank identity tensor
-            ind1 = ()
-            ind2 = ()
-            for d in sh:
-                i, j = indices(2)
-                dij = Identity(d)[i, j]
-                if res is None:
-                    res = dij
-                else:
-                    res *= dij
-                ind1 += (i,)
-                ind2 += (j,)
-            fp = as_tensor(res, ind1 + ind2)
-
-        return fp
-
-    def variable(self, o):
-        # Check cache
-        e, l = o.ufl_operands
-        c = self._variable_cache.get(l)
-
-        if c is not None:
-            return c
-
-        if o.label() == self._variable.label():
-            # dv/dv = identity of rank 2*rank(v)
-            op = self._make_self_diff_identity(o)
-        else:
-            # differentiate expression behind variable
-            e2, ep = self.visit(e)
-            op = ep
-            if not e2 == e:
-                o = Variable(e2, l)
-        # return variable and derivative of its expression
-        c = (o, op)
-        self._variable_cache[l] = c
-        return c
-
-class CoefficientAD(ForwardAD):
-    "Apply AFD (Automatic Functional Differentiation) to expression."
-    def __init__(self, coefficients, arguments, coefficient_derivatives, cache=None):
-        ForwardAD.__init__(self, var_shape=(), cache=cache)
-        ufl_assert(isinstance(coefficients, ExprList), "Expecting a ExprList.")
-        ufl_assert(isinstance(arguments, ExprList), "Expecting a ExprList.")
-        ufl_assert(isinstance(coefficient_derivatives, ExprMapping), "Expecting a ExprList.")
-        self._v = arguments
-        self._w = coefficients
-        cd = coefficient_derivatives.ufl_operands
-        self._cd = dict((cd[2*i], cd[2*i+1]) for i in range(len(cd)//2))
-
-    def coefficient(self, o):
-        # Define dw/dw := d/ds [w + s v] = v
-
-        debug("In CoefficientAD.coefficient:")
-        debug("o = %s" % o)
-        debug("self._w = %s" % self._w)
-        debug("self._v = %s" % self._v)
-
-        # Find o among w
-        for (w, v) in zip(self._w, self._v):
-            if o == w:
-                return (w, v)
-
-        # If o is not among coefficient derivatives, return do/dw=0
-        oprimesum = Zero(o.ufl_shape)
-        oprimes = self._cd.get(o)
-        if oprimes is None:
-            if self._cd:
-                # TODO: Make it possible to silence this message in particular?
-                #       It may be good to have for debugging...
-                warning("Assuming d{%s}/d{%s} = 0." % (o, self._w))
-        else:
-            # Make sure we have a tuple to match the self._v tuple
-            if not isinstance(oprimes, tuple):
-                oprimes = (oprimes,)
-                ufl_assert(len(oprimes) == len(self._v), "Got a tuple of arguments, "+
-                               "expecting a matching tuple of coefficient derivatives.")
-
-            # Compute do/dw_j = do/dw_h : v.
-            # Since we may actually have a tuple of oprimes and vs in a
-            # 'mixed' space, sum over them all to get the complete inner
-            # product. Using indices to define a non-compound inner product.
-            for (oprime, v) in zip(oprimes, self._v):
-                so, oi = as_scalar(oprime)
-                rv = len(v.ufl_shape)
-                oi1 = oi[:-rv]
-                oi2 = oi[-rv:]
-                prod = so*v[oi2]
-                if oi1:
-                    oprimesum += as_tensor(prod, oi1)
-                else:
-                    oprimesum += prod
-
-        # Example:
-        # (f : g) -> (dfdu : v) : g + ditto
-        # shape(f) == shape(g) == shape(dfdu : v)
-        # shape(dfdu) == shape(f) + shape(v)
-
-        return (o, oprimesum)
-
-    def grad(self, g):
-        # If we hit this type, it has already been propagated
-        # to a coefficient (or grad of a coefficient), # FIXME: Assert this!
-        # so we need to take the gradient of the variation or return zero.
-        # Complications occur when dealing with derivatives w.r.t. single components...
-
-        # Figure out how many gradients are around the inner terminal
-        ngrads = 0
-        o = g
-        while isinstance(o, Grad):
-            o, = o.ufl_operands
-            ngrads += 1
-        if not isinstance(o, FormArgument):
-            error("Expecting gradient of a FormArgument, not %r" % (o,))
-
-        def apply_grads(f):
-            if not isinstance(f, FormArgument):
-                print(','*60)
-                print(f)
-                print(o)
-                print(g)
-                print(','*60)
-                error("What?")
-            for i in range(ngrads):
-                f = Grad(f)
-            return f
-
-        # Find o among all w without any indexing, which makes this easy
-        for (w, v) in zip(self._w, self._v):
-            if o == w and isinstance(v, FormArgument):
-                # Case: d/dt [w + t v]
-                return (g, apply_grads(v))
-
-        # If o is not among coefficient derivatives, return do/dw=0
-        gprimesum = Zero(g.ufl_shape)
-
-        def analyse_variation_argument(v):
-            # Analyse variation argument
-            if isinstance(v, FormArgument):
-                # Case: d/dt [w[...] + t v]
-                vval, vcomp = v, ()
-            elif isinstance(v, Indexed):
-                # Case: d/dt [w + t v[...]]
-                # Case: d/dt [w[...] + t v[...]]
-                vval, vcomp = v.ufl_operands
-                vcomp = tuple(vcomp)
-            else:
-                error("Expecting argument or component of argument.")
-            ufl_assert(all(isinstance(k, FixedIndex) for k in vcomp),
-                       "Expecting only fixed indices in variation.")
-            return vval, vcomp
-
-        def compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp):
-            # Apply gradients directly to argument vval,
-            # and get the right indexed scalar component(s)
-            kk = indices(ngrads)
-            Dvkk = apply_grads(vval)[vcomp+kk]
-            # Place scalar component(s) Dvkk into the right tensor positions
-            if wshape:
-                Ejj, jj = unit_indexed_tensor(wshape, wcomp)
-            else:
-                Ejj, jj = 1, ()
-            gprimeterm = as_tensor(Ejj*Dvkk, jj+kk)
-            return gprimeterm
-
-        # Accumulate contributions from variations in different components
-        for (w, v) in zip(self._w, self._v):
-
-            # Analyse differentiation variable coefficient
-            if isinstance(w, FormArgument):
-                if not w == o:
-                    continue
-                wshape = w.ufl_shape
-
-                if isinstance(v, FormArgument):
-                    # Case: d/dt [w + t v]
-                    return (g, apply_grads(v))
-
-                elif isinstance(v, ListTensor):
-                    # Case: d/dt [w + t <...,v,...>]
-                    for wcomp, vsub in unwrap_list_tensor(v):
-                        if not isinstance(vsub, Zero):
-                            vval, vcomp = analyse_variation_argument(vsub)
-                            gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
-
-                else:
-                    ufl_assert(wshape == (), "Expecting scalar coefficient in this branch.")
-                    # Case: d/dt [w + t v[...]]
-                    wval, wcomp = w, ()
-
-                    vval, vcomp = analyse_variation_argument(v)
-                    gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
-
-            elif isinstance(w, Indexed): # This path is tested in unit tests, but not actually used?
-                # Case: d/dt [w[...] + t v[...]]
-                # Case: d/dt [w[...] + t v]
-                wval, wcomp = w.ufl_operands
-                if not wval == o:
-                    continue
-                assert isinstance(wval, FormArgument)
-                ufl_assert(all(isinstance(k, FixedIndex) for k in wcomp),
-                           "Expecting only fixed indices in differentiation variable.")
-                wshape = wval.ufl_shape
-
-                vval, vcomp = analyse_variation_argument(v)
-                gprimesum = gprimesum + compute_gprimeterm(ngrads, vval, vcomp, wshape, wcomp)
-
-            else:
-                error("Expecting coefficient or component of coefficient.")
-
-        # FIXME: Handle other coefficient derivatives: oprimes = self._cd.get(o)
-
-        if 0:
-            oprimes = self._cd.get(o)
-            if oprimes is None:
-                if self._cd:
-                    # TODO: Make it possible to silence this message in particular?
-                    #       It may be good to have for debugging...
-                    warning("Assuming d{%s}/d{%s} = 0." % (o, self._w))
-            else:
-                # Make sure we have a tuple to match the self._v tuple
-                if not isinstance(oprimes, tuple):
-                    oprimes = (oprimes,)
-                    ufl_assert(len(oprimes) == len(self._v), "Got a tuple of arguments, "+
-                                   "expecting a matching tuple of coefficient derivatives.")
-
-                # Compute dg/dw_j = dg/dw_h : v.
-                # Since we may actually have a tuple of oprimes and vs in a
-                # 'mixed' space, sum over them all to get the complete inner
-                # product. Using indices to define a non-compound inner product.
-                for (oprime, v) in zip(oprimes, self._v):
-                    error("FIXME: Figure out how to do this with ngrads")
-                    so, oi = as_scalar(oprime)
-                    rv = len(v.ufl_shape)
-                    oi1 = oi[:-rv]
-                    oi2 = oi[-rv:]
-                    prod = so*v[oi2]
-                    if oi1:
-                        gprimesum += as_tensor(prod, oi1)
-                    else:
-                        gprimesum += prod
-
-        return (g, gprimesum)
-
-    def variable(self, o):
-        # Check variable cache to reuse previously transformed variable if possible
-        e, l = o.ufl_operands
-        c = self._variable_cache.get(l)
-        if c is not None:
-            return c
-
-        # Visit the expression our variable represents
-        e2, ep = self.visit(e)
-        op = ep
-
-        # If the expression is not the same, reconstruct Variable object
-        o = self.reuse_if_possible(o, e2, l)
-
-        # Recreate Variable (with same label) and cache it
-        c = (o, op)
-        self._variable_cache[l] = c
-        return c
-
-def compute_grad_forward_ad(f, geometric_dimension):
-    alg = GradAD(geometric_dimension)
-    e, ediff = alg.visit(f)
-    return ediff
-
-def compute_variable_forward_ad(f, v):
-    alg = VariableAD(v)
-    e, ediff = alg.visit(f)
-    return ediff
-
-def compute_coefficient_forward_ad(f, w, v, cd):
-    alg = CoefficientAD(w, v, cd)
-    e, ediff = alg.visit(f)
-    return ediff
-
-def apply_nested_forward_ad(expr):
-    if expr._ufl_is_terminal_:
-        # A terminal needs no differentiation applied
-        return expr
-    elif not isinstance(expr, Derivative):
-        # Apply AD recursively to children
-        preops = expr.ufl_operands
-        postops = tuple(apply_nested_forward_ad(o) for o in preops)
-        # Reconstruct if necessary
-        need_reconstruct = not (preops == postops) # FIXME: Is this efficient? O(n)?
-        if need_reconstruct:
-            expr = expr._ufl_expr_reconstruct_(*postops)
-        return expr
-    elif isinstance(expr, Grad):
-        # Apply AD recursively to children
-        f, = expr.ufl_operands
-        f = apply_nested_forward_ad(f)
-        # Apply Grad-specialized AD to expanded child
-        gdim = expr.ufl_shape[-1]
-        return compute_grad_forward_ad(f, gdim)
-    elif isinstance(expr, VariableDerivative):
-        # Apply AD recursively to children
-        f, v = expr.ufl_operands
-        f = apply_nested_forward_ad(f)
-        # Apply Variable-specialized AD to expanded child
-        return compute_variable_forward_ad(f, v)
-    elif isinstance(expr, CoefficientDerivative):
-        # Apply AD recursively to children
-        f, w, v, cd = expr.ufl_operands
-        f = apply_nested_forward_ad(f)
-        # Apply Coefficient-specialized AD to expanded child
-        return compute_coefficient_forward_ad(f, w, v, cd)
-    else:
-        error("Unknown type.")
-
-# TODO: We could expand only the compound objects that have no rule
-#       before differentiating, to allow the AD to work on a coarser graph
-class UnusedADRules(object):
-
-    def _variable_derivative(self, o, f, v):
-        f, fp = f
-        v, vp = v
-        ufl_assert(isinstance(vp, Zero), "TODO: What happens if vp != 0, i.e. v depends the differentiation variable?")
-        # Are there any issues with indices here? Not sure, think through it...
-        oprime = o._ufl_expr_reconstruct_(fp, v)
-        return (o, oprime)
-
-    # --- Tensor algebra (compound types)
-
-    def outer(self, o, a, b):
-        a, ap = a
-        b, bp = b
-        return (o, outer(ap, b) + outer(a, bp)) # FIXME: Not valid for derivatives w.r.t. nonscalar variables!
-
-    def inner(self, o, a, b):
-        a, ap = a
-        b, bp = b
-        # FIXME: Rewrite with index notation (if necessary, depends on shapes)
-        # NB! Using b : ap because derivative axis should be
-        # last, in case of nonscalar differentiation variable!
-        return (o, inner(b, ap) + inner(a, bp)) # FIXME: Not correct, inner requires equal shapes!
-
-    def dot(self, o, a, b):
-        a, ap = a
-        b, bp = b
-        # FIXME: Rewrite with index notation (if necessary, depends on shapes)
-        # NB! Using b . ap because derivative axis should be
-        # last, in case of nonscalar differentiation variable!
-        return (o, dot(b, ap) + dot(a, bp))
-
-    def commute(self, o, a):
-        "This should work for all single argument operators that commute with d/dw with w scalar."
-        aprime = a[1]
-        return (o, o._ufl_expr_reconstruct_(aprime))
-
-    # FIXME: Not true for derivatives w.r.t. nonscalar variables...
-    transposed = commute
-    trace = commute
-    deviatoric = commute
-
-    # --- Compound differential operators, probably do not want...
-
-    # FIXME: nabla_div, nabla_grad
-    div  = commute
-    curl = commute
-    def grad(self, o, a):
-        a, aprime = a
-        if is_cellwise_constant(aprime):
-            oprime = self._make_zero_diff(o)
-        else:
-            oprime = o._ufl_expr_reconstruct_(aprime)
-        return (o, oprime)
-
-class UnimplementedADRules(object):
-
-    def cross(self, o, a, b):
-        error("Derivative of cross product not implemented, apply expand_compounds before AD.")
-        u, up = a
-        v, vp = b
-        #oprime = ...
-        return (o, oprime)
-
-    def determinant(self, o, a):
-        """FIXME: Some possible rules:
-
-        d detA / dv = detA * tr(inv(A) * dA/dv)
-
-        or
-
-        d detA / d row0 = cross(row1, row2)
-        d detA / d row1 = cross(row2, row0)
-        d detA / d row2 = cross(row0, row1)
-
-        i.e.
-
-        d detA / d A = [cross(row1, row2), cross(row2, row0), cross(row0, row1)] # or transposed or something
-        """
-        error("Derivative of determinant not implemented, apply expand_compounds before AD.")
-        A, Ap = a
-        #oprime = ...
-        return (o, oprime)
-
-    def cofactor(self, o, a):
-        error("Derivative of cofactor not implemented, apply expand_compounds before AD.")
-        A, Ap = a
-        #cofacA_prime = detA_prime*Ainv + detA*Ainv_prime
-        #oprime = ...
-        return (o, oprime)
-
-    def inverse(self, o, a):
-        """Derivation:
-        0 = d/dx [Ainv*A] = Ainv' * A + Ainv * A'
-        Ainv' * A = - Ainv * A'
-        Ainv' = - Ainv * A' * Ainv
-
-        K J = I
-        d/dv[r] (K[i,j] J[j,k]) = d/dv[r] K[i,j] J[j,k] + K[i,j] d/dv[r] J[j,k] = 0
-        d/dv[r] K[i,j] J[j,k] = -K[i,j] d/dv[r] J[j,k]
-        d/dv[r] K[i,j] J[j,k] K[k,s] = -K[i,j] d/dv[r] J[j,k] K[k,s]
-        d/dv[r] K[i,j] I[j,s] = -K[i,j] (d/dv[r] J[j,k]) K[k,s]
-        d/dv[r] K[i,s] = -K[i,j] (d/dv[r] J[j,k]) K[k,s]
-        """
-        A, Ap = a
-        return (o, -o*Ap*o) # FIXME: Need reshaping move derivative axis to the end of this expression
diff --git a/ufl/algorithms/map_integrands.py b/ufl/algorithms/map_integrands.py
index 5dd5440..2d20d47 100644
--- a/ufl/algorithms/map_integrands.py
+++ b/ufl/algorithms/map_integrands.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Basic algorithms for applying functions to subexpressions."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -23,38 +23,36 @@
 # which drags in a lot of stuff.
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.core.expr import Expr
 from ufl.corealg.map_dag import map_expr_dag
 from ufl.integral import Integral
 from ufl.form import Form
 from ufl.constantvalue import Zero
 
+
 def map_integrands(function, form, only_integral_type=None):
     """Apply transform(expression) to each integrand
     expression in form, or to form if it is an Expr.
     """
-
     if isinstance(form, Form):
-        mapped_integrals = [map_integrands(function, itg, only_integral_type) for itg in form.integrals()]
-        nonzero_integrals = [itg for itg in mapped_integrals if not isinstance(itg.integrand(), Zero)]
+        mapped_integrals = [map_integrands(function, itg, only_integral_type)
+                            for itg in form.integrals()]
+        nonzero_integrals = [itg for itg in mapped_integrals
+                             if not isinstance(itg.integrand(), Zero)]
         return Form(nonzero_integrals)
-
     elif isinstance(form, Integral):
         itg = form
         if (only_integral_type is None) or (itg.integral_type() in only_integral_type):
             return itg.reconstruct(function(itg.integrand()))
         else:
             return itg
-
     elif isinstance(form, Expr):
-        #ufl_assert(only_integral_type is None, "Restricting integral type is only valid with Form and Integral.")
         integrand = form
         return function(integrand)
-
     else:
         error("Expecting Form, Integral or Expr.")
 
 
 def map_integrand_dags(function, form, only_integral_type=None, compress=True):
-    return map_integrands(lambda expr: map_expr_dag(function, expr, compress), form, only_integral_type)
+    return map_integrands(lambda expr: map_expr_dag(function, expr, compress),
+                          form, only_integral_type)
diff --git a/ufl/algorithms/multifunction.py b/ufl/algorithms/multifunction.py
index 63736ea..80e1851 100644
--- a/ufl/algorithms/multifunction.py
+++ b/ufl/algorithms/multifunction.py
@@ -1,3 +1,5 @@
 # -*- coding: utf-8 -*-
-# Moved here to be usable in ufl.* files without depending on ufl.algorithms.*...
-from ufl.corealg.multifunction import MultiFunction
+# Moved here to be usable in ufl.* files without depending on
+# ufl.algorithms.*...
+
+from ufl.corealg.multifunction import MultiFunction # flake8: noqa
diff --git a/ufl/algorithms/pdiffs.py b/ufl/algorithms/pdiffs.py
deleted file mode 100644
index b77af30..0000000
--- a/ufl/algorithms/pdiffs.py
+++ /dev/null
@@ -1,247 +0,0 @@
-# -*- coding: utf-8 -*-
-"""This module defines partial differentiation rules for
-all relevant operands for use with reverse mode AD."""
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-#
-# Modified by Kristian B. Oelgaard, 2011
-
-from math import pi
-from ufl.log import error
-from ufl.assertions import ufl_assert
-from ufl.classes import Zero, IntValue
-from ufl.operators import cos, sin, cosh, sinh, exp, ln, sqrt, conditional, sign
-from ufl.tensors import unit_vectors, ListTensor
-from ufl.algorithms.multifunction import MultiFunction
-
-class PartialDerivativeComputer(MultiFunction):
-    """NB! The main reason for keeping this out of the Expr hierarchy is
-    to avoid user mistakes in the form of mixups with total derivatives,
-    and to allow both reverse and forward mode AD."""
-    def __init__(self):
-        MultiFunction.__init__(self)
-
-    # TODO: Make sure we have implemented partial derivatives of all operators.
-    #        At least non-compound ones should be covered, but compound ones
-    #        may be a good idea in future versions.
-
-    def expr(self, o):
-        error("No partial derivative defined for %s" % type(o))
-
-    # --- Basic algebra operators
-
-    def index_sum(self, f):
-        "d/dx sum_j x = TODO"
-        TODO
-
-    def sum(self, f):
-        "d/dx_i sum_j x_j = 1"
-        _1 = IntValue(1) # TODO: Handle non-scalars
-        return (_1,)*len(f.ufl_operands)
-
-    def product(self, f):
-        a, b = f.ufl_operands # TODO: Assuming binary operator for now
-        da = b # TODO: Is this right even for non-scalar b?
-        db = a
-        return (da, db)
-
-    def division(self, f):
-        """f = x/y
-        d/dx x/y = 1/y
-        d/dy x/y = -x/y**2 = -f/y"""
-        x, y = f.ufl_operands
-        # Nonscalar x not supported
-        ufl_assert(x.ufl_shape == (), "Expecting scalars in division.")
-        ufl_assert(y.ufl_shape == (), "Expecting scalars in division.")
-        d = 1 / y
-        return (d, -f*d)
-
-    def power(self, f):
-        """f = x**y
-        d/dx x**y = y*x**(y-1) = y*f/x
-        d/dy x**y = ln(x)*x**y = ln(x)*f"""
-        x, y = f.ufl_operands
-        dx = y*f/x
-        dy = ln(x)*f
-        return (dx, dy)
-
-    def abs(self, f):
-        r".. math:: \\frac{d}{dx} f(x) = \\frac{d}{dx} abs(x) = sign(x)"
-        x, = f.ufl_operands
-        dx = sign(x)
-        return (dx,)
-
-    # --- Mathfunctions
-
-    def sqrt(self, f):
-        "d/dx sqrt(x) = 1 / (2*sqrt(x))"
-        return (0.5/f,)
-
-    def exp(self, f):
-        "d/dx exp(x) = exp(x)"
-        return (f,)
-
-    def ln(self, f):
-        "d/dx ln x = 1 / x"
-        x, = f.ufl_operands
-        return (1/x,)
-
-    def cos(self, f):
-        "d/dx cos x = -sin(x)"
-        x, = f.ufl_operands
-        return (-sin(x),)
-
-    def sin(self, f):
-        "d/dx sin x = cos(x)"
-        x, = f.ufl_operands
-        return (cos(x),)
-
-    def tan(self, f):
-        "d/dx tan x = (sec(x))^2 = 2/(cos(2x) + 1)"
-        x, = f.ufl_operands
-        return (2.0/(cos(2.0*x) + 1.0),)
-
-    def cosh(self, f):
-        "d/dx cosh x = sinh(x)"
-        x, = f.ufl_operands
-        return (sinh(x),)
-
-    def sinh(self, f):
-        "d/dx sinh x = cosh(x)"
-        x, = f.ufl_operands
-        return (cosh(x),)
-
-    def tanh(self, f):
-        "d/dx tanh x = (sech(x))^2 = (2 cosh(x) / (cosh(2x) + 1))^2"
-        x, = f.ufl_operands
-        return (((2.0*cosh(x))/(cosh(2.0*x) + 1.0))**2,)
-
-    def acos(self, f):
-        r".. math:: \\frac{d}{dx} f(x) = \frac{d}{dx} \arccos(x) = \frac{-1}{\sqrt{1 - x^2}}"
-        x, = f.ufl_operands
-        return (-1.0/sqrt(1.0 - x**2),)
-
-    def asin(self, f):
-        "d/dx asin x = 1/sqrt(1 - x^2)"
-        x, = f.ufl_operands
-        return (1.0/sqrt(1.0 - x**2),)
-
-    def atan(self, f):
-        "d/dx atan x = 1/(1 + x^2)"
-        x, = f.ufl_operands
-        return (1.0/(1.0 + x**2),)
-
-    def atan_2(self, f):
-        """
-        f = atan2(x,y)
-        d/dx atan2(x,y) = y / (x**2 + y**2 )
-        d/dy atan2(x,y) = -x / (x**2 + y**2)
-        """
-        x, y = f.ufl_operands
-        d = x**2 + y**2
-        return (y/d, -x/d)
-
-    def erf(self, f):
-        "d/dx erf x = 2/sqrt(pi)*exp(-x^2)"
-        x, = f.ufl_operands
-        return (2.0/sqrt(pi)*exp(-x**2),)
-
-    def bessel_function(self, nu, x):
-        return NotImplemented
-
-    # --- Shape and indexing manipulators
-
-    def indexed(self, f): # TODO: Is this right? Fix for non-scalars too.
-        "d/dx x_i = (1)_i = 1"
-        s = f.ufl_shape
-        ufl_assert(s == (), "TODO: Assuming a scalar expression.")
-        _1 = IntValue(1) # TODO: Non-scalars
-        return (_1, None)
-
-    def list_tensor(self, f): # TODO: Is this right? Fix for higher order tensors too.
-        "d/dx_i [x_0, ..., x_n-1] = e_i (unit vector)"
-        ops = f.ufl_operands
-        n = len(ops)
-        s = ops[0].ufl_shape
-        ufl_assert(s == (), "TODO: Assuming a vector, i.e. scalar operands.")
-        return unit_vectors(n) # TODO: Non-scalars
-
-    def component_tensor(self, f):
-        x, i = f.ufl_operands
-        s = f.ufl_shape
-        ufl_assert(len(s) == 1, "TODO: Assuming a vector, i.e. scalar operands.")
-        n, = s
-        d = ListTensor([1]*n) # TODO: Non-scalars
-        return (d, None)
-
-    # --- Restrictions
-
-    def positive_restricted(self, f):
-        _1 = IntValue(1)
-        return (_1,) # or _1('+')? TODO: is this right?
-        # Note that _1('+') would become 0 with the current implementation
-
-    def negative_restricted(self, f):
-        _1 = IntValue(1)
-        return (_1,) # or _1('-')? TODO: is this right?
-
-    def cell_avg(self, f):
-        error("Not sure how to implement partial derivative of this operator at all actually.")
-
-    def facet_avg(self, f):
-        error("Not sure how to implement partial derivative of this operator at all actually.")
-
-    # --- Conditionals
-
-    def condition(self, f):
-        return (None, None)
-
-    def conditional(self, f): # TODO: Is this right? What about non-scalars?
-        c, a, b = f.ufl_operands
-        s = f.ufl_shape
-        ufl_assert(s == (), "TODO: Assuming scalar valued expressions.")
-        _0 = Zero()
-        _1 = IntValue(1)
-        da = conditional(c, _1, _0)
-        db = conditional(c, _0, _1)
-        return (None, da, db)
-
-    # --- Derivatives
-
-    def spatial_derivative(self, f):
-        error("Partial derivative of spatial_derivative not implemented, "
-              "when is this called? apply_ad should make sure it isn't called.")
-        x, i = f.ufl_operands
-        return (None, None)
-
-    def variable_derivative(self, f):
-        error("Partial derivative of variable_derivative not implemented, "
-              "when is this called? apply_ad should make sure it isn't called.")
-        x, v = f.ufl_operands
-        return (None, None)
-
-    def coefficient_derivative(self, f):
-        error("Partial derivative of coefficient_derivative not implemented, "
-              "when is this called? apply_ad should make sure it isn't called.")
-        a, w, v = f.ufl_operands
-        return (None, None, None)
-
-# Example usage:
-def pdiffs(exprs):
-    pd = PartialDerivativeComputer()
-    return [pd(e) for e in exprs]
diff --git a/ufl/algorithms/predicates.py b/ufl/algorithms/predicates.py
deleted file mode 100644
index 4665e44..0000000
--- a/ufl/algorithms/predicates.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- coding: utf-8 -*-
-"""Functions to check properties of forms and integrals."""
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
-from ufl.log import warning, debug
-from ufl.algorithms.traversal import iter_expressions
-from ufl.algorithms.argument_dependencies import extract_argument_dependencies, NotMultiLinearException
-
-#--- Utilities for checking properties of forms ---
-
-def is_multilinear(form):
-    "Check if form is multilinear in arguments."
-    # An attempt at implementing is_multilinear using extract_argument_dependencies.
-    # TODO: This has some false negatives for "multiple configurations". (Does it still? Needs testing!)
-    # TODO: FFC probably needs a variant of this which checks for some sorts of linearity
-    #       in Coefficients as well, this should be a fairly simple extension of the current algorithm.
-    try:
-        for e in iter_expressions(form):
-            deps = extract_argument_dependencies(e)
-            nargs = [len(d) for d in deps]
-            if len(nargs) == 0:
-                debug("This form is a functional.")
-            if len(nargs) == 1:
-                debug("This form is linear in %d arguments." % nargs[0])
-            if len(nargs) > 1:
-                warning("This form has more than one argument "
-                    "'configuration', it has terms that are linear in %s "
-                    "arguments respectively." % str(nargs))
-
-    except NotMultiLinearException as msg:
-        warning("Form is not multilinear, the offending term is: %s" % msg)
-        return False
-
-    return True
diff --git a/ufl/algorithms/renumbering.py b/ufl/algorithms/renumbering.py
index df33a8f..86f32b6 100644
--- a/ufl/algorithms/renumbering.py
+++ b/ufl/algorithms/renumbering.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Algorithms for renumbering of counted objects, currently variables and indices."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -19,13 +19,13 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 from six.moves import zip
-from ufl.utils.stacks import Stack, StackDict
 from ufl.log import error
 from ufl.core.expr import Expr
 from ufl.core.multiindex import Index, FixedIndex, MultiIndex
 from ufl.variable import Label, Variable
 from ufl.algorithms.transformer import ReuseTransformer, apply_transformer
-from ufl.assertions import ufl_assert
+from ufl.classes import Zero
+
 
 class VariableRenumberingTransformer(ReuseTransformer):
     def __init__(self):
@@ -42,6 +42,7 @@ class VariableRenumberingTransformer(ReuseTransformer):
             self.variable_map[l] = v
         return v
 
+
 class IndexRenumberingTransformer(VariableRenumberingTransformer):
     "This is a poorly designed algorithm. It is used in some tests, please do not use for anything else."
     def __init__(self):
@@ -71,14 +72,14 @@ class IndexRenumberingTransformer(VariableRenumberingTransformer):
         new_indices = tuple(self.index(i) for i in o.indices())
         return MultiIndex(new_indices)
 
+
 def renumber_indices(expr):
     if isinstance(expr, Expr):
         num_free_indices = len(expr.ufl_free_indices)
-        #error("Not expecting any free indices left in expression.")
 
     result = apply_transformer(expr, IndexRenumberingTransformer())
 
     if isinstance(expr, Expr):
-        ufl_assert(num_free_indices == len(result.ufl_free_indices),
-                   "The number of free indices left in expression should be invariant w.r.t. renumbering.")
+        if num_free_indices != len(result.ufl_free_indices):
+            error("The number of free indices left in expression should be invariant w.r.t. renumbering.")
     return result
diff --git a/ufl/algorithms/replace.py b/ufl/algorithms/replace.py
index 18c20cf..4836015 100644
--- a/ufl/algorithms/replace.py
+++ b/ufl/algorithms/replace.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithm for replacing terminals in an expression."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -23,21 +23,21 @@
 from six import iteritems, iterkeys
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.classes import CoefficientDerivative
 from ufl.constantvalue import as_ufl
 from ufl.corealg.multifunction import MultiFunction
 from ufl.algorithms.map_integrands import map_integrand_dags
 from ufl.algorithms.analysis import has_exact_type
 
+
 class Replacer(MultiFunction):
     def __init__(self, mapping):
         MultiFunction.__init__(self)
         self._mapping = mapping
-        ufl_assert(all(k._ufl_is_terminal_ for k in iterkeys(mapping)),
-            "This implementation can only replace Terminal objects.")
-        ufl_assert(all(k.ufl_shape == v.ufl_shape for k, v in iteritems(mapping)),
-            "Replacement expressions must have the same shape as what they replace.")
+        if not all(k._ufl_is_terminal_ for k in iterkeys(mapping)):
+            error("This implementation can only replace Terminal objects.")
+        if not all(k.ufl_shape == v.ufl_shape for k, v in iteritems(mapping)):
+            error("Replacement expressions must have the same shape as what they replace.")
 
     expr = MultiFunction.reuse_if_untouched
 
@@ -51,6 +51,7 @@ class Replacer(MultiFunction):
     def coefficient_derivative(self, o):
         error("Derivatives should be applied before executing replace.")
 
+
 def replace(e, mapping):
     """Replace terminal objects in expression.
 
diff --git a/ufl/algorithms/signature.py b/ufl/algorithms/signature.py
index bd3a7b5..274fd31 100644
--- a/ufl/algorithms/signature.py
+++ b/ufl/algorithms/signature.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Signature computation for forms."""
 
-# Copyright (C) 2012-2015 Martin Sandve Alnæs
+# Copyright (C) 2012-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,17 +19,17 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 import hashlib
-from ufl.classes import (Terminal, Label,
+from ufl.classes import (Label,
                          Index, MultiIndex,
-                         Coefficient, Argument, FormArgument,
+                         Coefficient, Argument,
                          GeometricQuantity, ConstantValue,
                          ExprList, ExprMapping)
 from ufl.log import error
+from ufl.utils.py23 import as_bytes
 from ufl.corealg.traversal import traverse_unique_terminals, pre_traversal
-from ufl.utils.sorting import sorted_by_count
-from ufl.domain import join_domains
 from ufl.algorithms.domain_analysis import canonicalize_metadata
 
+
 def compute_multiindex_hashdata(expr, index_numbering):
     data = []
     for i in expr:
@@ -45,15 +45,15 @@ def compute_multiindex_hashdata(expr, index_numbering):
             data.append(int(i))
     return tuple(data)
 
+
 def compute_terminal_hashdata(expressions, renumbering):
 
     if not isinstance(expressions, list):
         expressions = [expressions]
     assert renumbering is not None
 
-    # Extract a unique numbering of free indices,
-    # as well as form arguments, and just take
-    # repr of the rest of the terminals while
+    # Extract a unique numbering of free indices, as well as form
+    # arguments, and just take repr of the rest of the terminals while
     # we're iterating over them
     terminal_hashdata = {}
     labels = {}
@@ -62,7 +62,8 @@ def compute_terminal_hashdata(expressions, renumbering):
         for expr in traverse_unique_terminals(expression):
 
             if isinstance(expr, MultiIndex):
-                # Indices need a canonical numbering for a stable signature, thus this algorithm
+                # Indices need a canonical numbering for a stable
+                # signature, thus this algorithm
                 data = compute_multiindex_hashdata(expr, index_numbering)
 
             elif isinstance(expr, ConstantValue):
@@ -78,7 +79,8 @@ def compute_terminal_hashdata(expressions, renumbering):
                 data = expr._ufl_signature_data_(renumbering)
 
             elif isinstance(expr, Label):
-                # Numbering labels as we visit them # TODO: Include in renumbering
+                # Numbering labels as we visit them # TODO: Include in
+                # renumbering
                 data = labels.get(expr)
                 if data is None:
                     data = "L%d" % len(labels)
@@ -99,36 +101,40 @@ def compute_terminal_hashdata(expressions, renumbering):
 
     return terminal_hashdata
 
+
 def compute_expression_hashdata(expression, terminal_hashdata):
-    # The hashdata computed here can be interpreted as
-    # prefix operator notation, i.e. we store the equivalent
-    # of '+ * a b * c d' for the expression (a*b)+(c*d)
+    # The hashdata computed here can be interpreted as prefix operator
+    # notation, i.e. we store the equivalent of '+ * a b * c d' for
+    # the expression (a*b)+(c*d)
     expression_hashdata = []
     for expr in pre_traversal(expression):
         if expr._ufl_is_terminal_:
             data = terminal_hashdata[expr]
         else:
-            data = expr._ufl_typecode_ # TODO: Use expr._ufl_signature_data_()? More extensible, but more overhead.
+            data = expr._ufl_typecode_  # TODO: Use expr._ufl_signature_data_()? More extensible, but more overhead.
         expression_hashdata.append(data)
     # Oneliner: TODO: Benchmark, maybe use a generator?
-    #expression_hashdata = [(terminal_hashdata[expr] if expr._ufl_is_terminal_ else expr._ufl_typecode_)
+    # expression_hashdata = [(terminal_hashdata[expr] if expr._ufl_is_terminal_ else expr._ufl_typecode_)
     #                       for expr in pre_traversal(expression)]
     return expression_hashdata
 
-def compute_expression_signature(expr, renumbering): # FIXME: Fix callers
+
+def compute_expression_signature(expr, renumbering):  # FIXME: Fix callers
     # FIXME: Rewrite in terms of compute_form_signature?
 
     # Build hashdata for all terminals first
     terminal_hashdata = compute_terminal_hashdata([expr], renumbering)
 
     # Build hashdata for full expression
-    expression_hashdata = compute_expression_hashdata(expr,
-                                                      terminal_hashdata)
+    expression_hashdata = compute_expression_hashdata(expr, terminal_hashdata)
+
+    # Pass it through a seriously overkill hashing algorithm
+    # (should we use sha1 instead?)
+    data = as_bytes(str(expression_hashdata))
+    return hashlib.sha512(data).hexdigest()
 
-    # Pass it through a seriously overkill hashing algorithm :) TODO: How fast is this? Reduce?
-    return hashlib.sha512(str(expression_hashdata).encode('utf-8')).hexdigest()
 
-def compute_form_signature(form, renumbering): # FIXME: Fix callers
+def compute_form_signature(form, renumbering):  # FIXME: Fix callers
     # Extract integrands
     integrals = form.integrals()
     integrands = [integral.integrand() for integral in integrals]
@@ -142,23 +148,26 @@ def compute_form_signature(form, renumbering): # FIXME: Fix callers
     for integral in integrals:
         # Compute hash data for expression, this is the expensive part
         integrand_hashdata = compute_expression_hashdata(integral.integrand(),
-                                                          terminal_hashdata)
+                                                         terminal_hashdata)
 
         domain_hashdata = integral.ufl_domain()._ufl_signature_data_(renumbering)
 
-        # Collect all data about integral that should be reflected in signature,
-        # including compiler data but not domain data, because compiler data
-        # affects the way the integral is compiled while domain data is only
-        # carried for convenience in the problem solving environment.
+        # Collect all data about integral that should be reflected in
+        # signature, including compiler data but not domain data,
+        # because compiler data affects the way the integral is
+        # compiled while domain data is only carried for convenience
+        # in the problem solving environment.
         integral_hashdata = (
             integrand_hashdata,
             domain_hashdata,
             integral.integral_type(),
             integral.subdomain_id(),
             canonicalize_metadata(integral.metadata()),
-            )
+        )
 
         hashdata.append(integral_hashdata)
 
-    # Pass hashdata through a seriously overkill hashing algorithm :) TODO: How fast is this? Reduce?
-    return hashlib.sha512(str(hashdata).encode('utf-8')).hexdigest()
+    # Pass it through a seriously overkill hashing algorithm
+    # (should we use sha1 instead?)
+    data = as_bytes(str(hashdata))
+    return hashlib.sha512(data).hexdigest()
diff --git a/ufl/algorithms/transformer.py b/ufl/algorithms/transformer.py
index 9dc1df8..90fec7c 100644
--- a/ufl/algorithms/transformer.py
+++ b/ufl/algorithms/transformer.py
@@ -4,7 +4,7 @@ basic specializations to further base other algorithms upon,
 as well as some utilities for easier application of such
 algorithms."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -24,15 +24,10 @@ algorithms."""
 # Modified by Anders Logg, 2009-2010
 
 from inspect import getargspec
-from ufl.log import error, debug
-from ufl.assertions import ufl_assert
-
-from ufl.classes import Expr, Terminal, Variable, Zero, all_ufl_classes
+from ufl.log import error
+from ufl.classes import Variable, all_ufl_classes
 from ufl.algorithms.map_integrands import map_integrands
 
-from ufl.integral import Integral
-from ufl.form import Form
-
 
 def is_post_handler(function):
     "Is this a handler that expects transformed children as input?"
@@ -41,10 +36,12 @@ def is_post_handler(function):
     visit_children_first = num_args > 2
     return visit_children_first
 
+
 class Transformer(object):
     """Base class for a visitor-like algorithm design pattern used to
     transform expression trees from one representation to another."""
     _handlers_cache = {}
+
     def __init__(self, variable_cache=None):
         if variable_cache is None:
             variable_cache = {}
@@ -61,23 +58,26 @@ class Transformer(object):
                 # (NB! This assumes that all UFL classes inherits a single
                 # Expr subclass and that this is the first superclass!)
                 for c in classobject.mro():
-                    # Register classobject with handler for the first encountered superclass
-                    name = c._ufl_handler_name_
-                    function = getattr(self, name, None)
+                    # Register classobject with handler for the first
+                    # encountered superclass
+                    handler_name = c._ufl_handler_name_
+                    function = getattr(self, handler_name, None)
                     if function:
-                        cache_data[classobject._ufl_typecode_] = name, is_post_handler(function)
+                        cache_data[classobject._ufl_typecode_] = handler_name, is_post_handler(function)
                         break
             Transformer._handlers_cache[type(self)] = cache_data
 
-        # Build handler list for this particular class (get functions bound to self)
+        # Build handler list for this particular class (get functions
+        # bound to self)
         self._handlers = [(getattr(self, name), post) for (name, post) in cache_data]
-
-        # Keep a stack of objects visit is called on, to ease backtracking
+        # Keep a stack of objects visit is called on, to ease
+        # backtracking
         self._visit_stack = []
 
     def print_visit_stack(self):
         print("/"*80)
         print("Visit stack in Transformer:")
+
         def sstr(s):
             ss = str(type(s)) + " ; "
             n = 160 - len(ss)
@@ -86,18 +86,19 @@ class Transformer(object):
         print("\\"*80)
 
     def visit(self, o):
-        #debug("Visiting object of type %s." % type(o).__name__)
         # Update stack
         self._visit_stack.append(o)
 
-        # Get handler for the UFL class of o (type(o) may be an external subclass of the actual UFL class)
+        # Get handler for the UFL class of o (type(o) may be an
+        # external subclass of the actual UFL class)
         h, visit_children_first = self._handlers[o._ufl_typecode_]
 
-        #if not h:
+        # if not h:
         #    # Failed to find a handler! Should never happen, but will happen if a non-Expr object is visited.
         #    error("Can't handle objects of type %s" % str(type(o)))
 
-        # Is this a handler that expects transformed children as input?
+        # Is this a handler that expects transformed children as
+        # input?
         if visit_children_first:
             # Yes, visit all children first and then call h.
             r = h(o, *[self.visit(op) for op in o.ufl_operands])
@@ -146,7 +147,8 @@ class Transformer(object):
     terminal = reuse
 
     def reuse_variable(self, o):
-        # Check variable cache to reuse previously transformed variable if possible
+        # Check variable cache to reuse previously transformed
+        # variable if possible
         e, l = o.ufl_operands
         v = self._variable_cache.get(l)
         if v is not None:
@@ -167,7 +169,8 @@ class Transformer(object):
         return v
 
     def reconstruct_variable(self, o):
-        # Check variable cache to reuse previously transformed variable if possible
+        # Check variable cache to reuse previously transformed
+        # variable if possible
         e, l = o.ufl_operands
         v = self._variable_cache.get(l)
         if v is not None:
@@ -223,11 +226,13 @@ def apply_transformer(e, transformer, integral_type=None):
     expression in form, or to form if it is an Expr."""
     return map_integrands(lambda expr: transformer.visit(expr), e, integral_type)
 
+
 def ufl2ufl(e):
     """Convert an UFL expression to a new UFL expression, with no changes.
     This is used for testing that objects in the expression behave as expected."""
     return apply_transformer(e, ReuseTransformer())
 
+
 def ufl2uflcopy(e):
     """Convert an UFL expression to a new UFL expression.
     All nonterminal object instances are replaced with identical
@@ -235,6 +240,7 @@ def ufl2uflcopy(e):
     testing that objects in the expression behave as expected."""
     return apply_transformer(e, CopyTransformer())
 
+
 def strip_variables(e):
     "Replace all Variable instances with the expression they represent."
     return apply_transformer(e, VariableStripper())
diff --git a/ufl/algorithms/traversal.py b/ufl/algorithms/traversal.py
index a81da28..41b1858 100644
--- a/ufl/algorithms/traversal.py
+++ b/ufl/algorithms/traversal.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module contains algorithms for traversing expression trees in different ways."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -25,7 +25,8 @@ from ufl.core.expr import Expr
 from ufl.integral import Integral
 from ufl.form import Form
 
-#--- Traversal utilities ---
+
+# --- Traversal utilities ---
 
 def iter_expressions(a):
     """Utility function to handle Form, Integral and any Expr
@@ -42,6 +43,3 @@ def iter_expressions(a):
     elif isinstance(a, Expr):
         return (a,)
     error("Not an UFL type: %s" % str(type(a)))
-
-# The rest is moved here:
-#from ufl.corealg.traversal import pre_traversal, post_traversal, traverse_terminals, traverse_unique_terminals
diff --git a/ufl/argument.py b/ufl/argument.py
index 7fac0c5..e9f3ac7 100644
--- a/ufl/argument.py
+++ b/ufl/argument.py
@@ -2,7 +2,7 @@
 """This module defines the class Argument and a number of related
 classes (functions), including TestFunction and TrialFunction."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,19 +20,21 @@ classes (functions), including TestFunction and TrialFunction."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2008-2009.
+# Modified by Massimiliano Leoni, 2016.
 
-from ufl.log import deprecate
-from ufl.assertions import ufl_assert
+import numbers
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 from ufl.core.ufl_type import ufl_type
-from ufl.core.terminal import Terminal, FormArgument
+from ufl.core.terminal import FormArgument
 from ufl.split_functions import split
 from ufl.finiteelement import FiniteElementBase
 from ufl.domain import default_domain
 from ufl.functionspace import AbstractFunctionSpace, FunctionSpace
 
-
 # Export list for ufl.classes (TODO: not actually classes: drop? these are in ufl.*)
-__all_classes__ = ["TestFunction", "TrialFunction", "TestFunctions", "TrialFunctions"]
+__all_classes__ = as_native_strings(["TestFunction", "TrialFunction", "TestFunctions", "TrialFunctions"])
 
 
 # --- Class representing an argument (basis function) in a form ---
@@ -40,13 +42,20 @@ __all_classes__ = ["TestFunction", "TrialFunction", "TestFunctions", "TrialFunct
 @ufl_type()
 class Argument(FormArgument):
     """UFL value: Representation of an argument to a form."""
-    __slots__ = ("_ufl_function_space", "_ufl_shape", "_number", "_part", "_repr")
+    __slots__ = as_native_strings((
+        "_ufl_function_space",
+        "_ufl_shape",
+        "_number",
+        "_part",
+        "_repr",
+    ))
 
     def __init__(self, function_space, number, part=None):
         FormArgument.__init__(self)
 
         if isinstance(function_space, FiniteElementBase):
-            # For legacy support for .ufl files using cells, we map the cell to The Default Mesh
+            # For legacy support for .ufl files using cells, we map the cell to
+            # the default Mesh
             element = function_space
             domain = default_domain(element.cell())
             function_space = FunctionSpace(domain, element)
@@ -56,17 +65,19 @@ class Argument(FormArgument):
         self._ufl_function_space = function_space
         self._ufl_shape = function_space.ufl_element().value_shape()
 
-        ufl_assert(isinstance(number, int),
-                   "Expecting an int for number, not %s" % (number,))
-        ufl_assert(part is None or isinstance(part, int),
-                   "Expecting None or an int for part, not %s" % (part,))
+        if not isinstance(number, numbers.Integral):
+            error("Expecting an int for number, not %s" % (number,))
+        if part is not None and not isinstance(part, numbers.Integral):
+            error("Expecting None or an int for part, not %s" % (part,))
         self._number = number
         self._part = part
 
-        self._repr = "Argument(%r, %r, %r)" % (self._ufl_function_space, self._number, self._part)
+        self._repr = as_native_str("Argument(%s, %s, %s)" % (
+            repr(self._ufl_function_space), repr(self._number), repr(self._part)))
 
     @property
     def ufl_shape(self):
+        "Return the associated UFL shape."
         return self._ufl_shape
 
     def ufl_function_space(self):
@@ -74,18 +85,24 @@ class Argument(FormArgument):
         return self._ufl_function_space
 
     def ufl_domain(self):
-        #TODO: deprecate("Argument.ufl_domain() is deprecated, please use .ufl_function_space().ufl_domain() instead.")
+        "Deprecated, please use .ufl_function_space().ufl_domain() instead."
+        # TODO: deprecate("Argument.ufl_domain() is deprecated, please
+        # use .ufl_function_space().ufl_domain() instead.")
         return self._ufl_function_space.ufl_domain()
 
     def ufl_element(self):
-        #TODO: deprecate("Argument.ufl_domain() is deprecated, please use .ufl_function_space().ufl_element() instead.")
+        "Deprecated, please use .ufl_function_space().ufl_element() instead."
+        # TODO: deprecate("Argument.ufl_domain() is deprecated, please
+        # use .ufl_function_space().ufl_element() instead.")
         return self._ufl_function_space.ufl_element()
 
-    def element(self):
-        deprecate("Argument.element() is deprecated, please use Argument.ufl_element() instead.")
-        return self.ufl_element()
+    # def element(self):
+    #    "Deprecated, please use .ufl_function_space().ufl_element() instead."
+    #    deprecate("Argument.element() is deprecated, please use Argument.ufl_element() instead.")
+    #    return self.ufl_element()
 
     def number(self):
+        "Return the Argument number."
         return self._number
 
     def part(self):
@@ -100,8 +117,9 @@ class Argument(FormArgument):
         return False
 
     def ufl_domains(self):
-        "Return tuple of domains related to this terminal object."
-        #TODO: deprecate("Argument.ufl_domains() is deprecated, please use .ufl_function_space().ufl_domains() instead.")
+        "Deprecated, please use .ufl_function_space().ufl_domains() instead."
+        # TODO: deprecate("Argument.ufl_domains() is deprecated,
+        # please use .ufl_function_space().ufl_domains() instead.")
         return self._ufl_function_space.ufl_domains()
 
     def _ufl_signature_data_(self, renumbering):
@@ -143,16 +161,19 @@ class Argument(FormArgument):
                 self._part == other._part and
                 self._ufl_function_space == other._ufl_function_space)
 
+
 # --- Helper functions for pretty syntax ---
 
 def TestFunction(function_space, part=None):
     """UFL value: Create a test function argument to a form."""
     return Argument(function_space, 0, part)
 
+
 def TrialFunction(function_space, part=None):
     """UFL value: Create a trial function argument to a form."""
     return Argument(function_space, 1, part)
 
+
 # --- Helper functions for creating subfunctions on mixed elements ---
 
 def Arguments(function_space, number):
@@ -160,11 +181,13 @@ def Arguments(function_space, number):
     tuple with the function components corresponding to the subelements."""
     return split(Argument(function_space, number))
 
+
 def TestFunctions(function_space):
     """UFL value: Create a TestFunction in a mixed space, and return a
     tuple with the function components corresponding to the subelements."""
     return Arguments(function_space, 0)
 
+
 def TrialFunctions(function_space):
     """UFL value: Create a TrialFunction in a mixed space, and return a
     tuple with the function components corresponding to the subelements."""
diff --git a/ufl/assertions.py b/ufl/assertions.py
index b1225c3..b11dd5d 100644
--- a/ufl/assertions.py
+++ b/ufl/assertions.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module provides assertion functions used by the UFL implementation."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,25 +20,37 @@
 
 from ufl.log import error
 
-#--- Standardized error messages ---
+
+# TODO: Move to this file and make other files import from here
+from ufl.core.expr import ufl_err_str
+
+
+# TODO: Use these and add more
+# --- Standardized error messages ---
 
 def expecting_instance(v, c):
-    error("Expecting %s instance, not %s." % (c.__name__, repr(v)))
+    error("Expecting %s instance, not %s." % (c.__name__, ufl_err_str(v)))
+
 
 def expecting_python_scalar(v):
-    error("Expecting Python scalar, not %s." % repr(v))
+    error("Expecting Python scalar, not %s." % ufl_err_str(v))
+
 
 def expecting_expr(v):
-    error("Expecting Expr instance, not %s." % repr(v))
+    error("Expecting Expr instance, not %s." % ufl_err_str(v))
+
 
 def expecting_terminal(v):
-    error("Expecting Terminal instance, not %s." % repr(v))
+    error("Expecting Terminal instance, not %s." % ufl_err_str(v))
+
 
 def expecting_true_ufl_scalar(v):
-    error("Expecting UFL scalar expression with no free indices, not %s." % repr(v))
+    error("Expecting UFL scalar expression with no free indices, not %s." % ufl_err_str(v))
+
 
-#--- Standardized assertions ---
+# --- Standardized assertions ---
 
+# TODO: Stop using this
 def ufl_assert(condition, *message):
     "Assert that condition is true and otherwise issue an error with given message."
     if not condition:
diff --git a/ufl/cell.py b/ufl/cell.py
index 8b5d0f6..51f8771 100644
--- a/ufl/cell.py
+++ b/ufl/cell.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Types for representing a cell."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -22,32 +22,39 @@
 # Modified by Kristian B. Oelgaard, 2009
 # Modified by Marie E. Rognes 2012
 # Modified by Andrew T. T. McRae, 2014
+# Modified by Massimiliano Leoni, 2016
 
-from ufl.log import warning, error
-from ufl.assertions import ufl_assert
-from ufl.utils.formatting import istr
-from ufl.utils.dicts import EmptyDict
-from ufl.core.terminal import Terminal
+from six.moves import reduce
+from six import string_types
+import numbers
+
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 from ufl.core.ufl_type import attach_operators_from_hash_data
 
 
 # Export list for ufl.classes
-__all_classes__ = ["AbstractCell", "Cell", "TensorProductCell", "OuterProductCell"]
+__all_classes__ = as_native_strings(["AbstractCell", "Cell", "TensorProductCell"])
 
 
 # --- The most abstract cell class, base class for other cell types
 
 class AbstractCell(object):
     "Representation of an abstract finite element cell with only the dimensions known."
-    __slots__ = ("_topological_dimension", "_geometric_dimension")
+    __slots__ = as_native_strings((
+        "_topological_dimension",
+        "_geometric_dimension",
+        ))
+
     def __init__(self, topological_dimension, geometric_dimension):
         # Validate dimensions
-        ufl_assert(isinstance(geometric_dimension, int),
-                   "Expecting integer geometric dimension, not '%r'" % (geometric_dimension,))
-        ufl_assert(isinstance(topological_dimension, int),
-                   "Expecting integer topological dimension, not '%r'" % (topological_dimension,))
-        ufl_assert(topological_dimension <= geometric_dimension,
-                   "Topological dimension cannot be larger than geometric dimension.")
+        if not isinstance(geometric_dimension, numbers.Integral):
+            error("Expecting integer geometric_dimension.")
+        if not isinstance(topological_dimension, numbers.Integral):
+            error("Expecting integer topological_dimension.")
+        if topological_dimension > geometric_dimension:
+            error("Topological dimension cannot be larger than geometric dimension.")
 
         # Store validated dimensions
         self._topological_dimension = topological_dimension
@@ -73,55 +80,60 @@ class AbstractCell(object):
         "Define an arbitrarily chosen but fixed sort order for all cells."
         if not isinstance(other, AbstractCell):
             return NotImplemented
-        # Sort by gdim first, tdim next, then whatever's left depending on the subclass
+        # Sort by gdim first, tdim next, then whatever's left
+        # depending on the subclass
         s = (self.geometric_dimension(), self.topological_dimension())
         o = (other.geometric_dimension(), other.topological_dimension())
         if s != o:
             return s < o
         return self._ufl_hash_data_() < other._ufl_hash_data_()
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
 
 # --- Basic topological properties of known basic cells
 
-# Mapping from cell name to number of cell entities of each topological dimension
-num_cell_entities = {
-    "vertex":        (1,),
-    "interval":      (2,  1),
-    "triangle":      (3,  3, 1),
-    "quadrilateral": (4,  4, 1),
-    "tetrahedron":   (4,  6, 4, 1),
-    "hexahedron":    (8, 12, 6, 1),
-    }
+# Mapping from cell name to number of cell entities of each
+# topological dimension
+num_cell_entities = {"vertex": (1,),
+                     "interval": (2, 1),
+                     "triangle": (3, 3, 1),
+                     "quadrilateral": (4, 4, 1),
+                     "tetrahedron": (4, 6, 4, 1),
+                     "hexahedron": (8, 12, 6, 1)}
 
 # Mapping from cell name to topological dimension
-cellname2dim = dict((k, len(v)-1) for k,v in num_cell_entities.items())
+cellname2dim = dict((k, len(v)-1) for k, v in num_cell_entities.items())
 
 # Mapping from cell name to facet name
-# Note: This is not generalizable to product elements but it's still in use a couple of places.
-cellname2facetname = {
-    "interval":      "vertex",
-    "triangle":      "interval",
-    "quadrilateral": "interval",
-    "tetrahedron":   "triangle",
-    "hexahedron":    "quadrilateral",
-    }
+# Note: This is not generalizable to product elements but it's still
+# in use a couple of places.
+cellname2facetname = {"interval": "vertex",
+                      "triangle": "interval",
+                      "quadrilateral": "interval",
+                      "tetrahedron": "triangle",
+                      "hexahedron": "quadrilateral"}
 
 
 # --- Basic cell representation classes
 
+# @six.python_2_unicode_compatible
 @attach_operators_from_hash_data
 class Cell(AbstractCell):
     "Representation of a named finite element cell with known structure."
-    __slots__ = ("_cellname",)
+    __slots__ = as_native_strings(("_cellname",))
+
     def __init__(self, cellname, geometric_dimension=None):
         "Initialize basic cell description."
 
         self._cellname = cellname
 
-        # The topological dimension is defined by the cell type,
-        # so the cellname must be among the known ones,
-        # so we can find the known dimension, unless we have
-        # a product cell, in which the given dimension is used
+        # The topological dimension is defined by the cell type, so
+        # the cellname must be among the known ones, so we can find
+        # the known dimension, unless we have a product cell, in which
+        # the given dimension is used
         topological_dimension = len(num_cell_entities[cellname]) - 1
 
         # The geometric dimension defaults to equal the topological
@@ -134,10 +146,17 @@ class Cell(AbstractCell):
 
     # --- Overrides of AbstractCell methods ---
 
+    def reconstruct(self, geometric_dimension=None):
+        if geometric_dimension is None:
+            geometric_dimension = self._geometric_dimension
+        return Cell(self._cellname, geometric_dimension=geometric_dimension)
+
     def is_simplex(self):
+        "    Return True if this is a simplex cell."
         return self.num_vertices() == self.topological_dimension() + 1
 
     def has_simplex_facets(self):
+        "Return True if all the facets of this cell are simplex cells."
         return self.is_simplex() or self.cellname() == "quadrilateral"
 
     # --- Specific cell properties ---
@@ -178,32 +197,54 @@ class Cell(AbstractCell):
         return s
 
     def __repr__(self):
-        # For standard cells, return name of builtin cell object if possible.
-        # This reduces the size of the repr strings for domains, elements, etc. as well
+        # For standard cells, return name of builtin cell object if
+        # possible.  This reduces the size of the repr strings for
+        # domains, elements, etc. as well
         gdim = self.geometric_dimension()
         tdim = self.topological_dimension()
         name = self.cellname()
         if gdim == tdim and name in cellname2dim:
-            return name
+            r = name
         else:
-            return "Cell(%r, %r)" % (name, gdim)
+            r = "Cell(%s, %s)" % (repr(name), repr(gdim))
+        return as_native_str(r)
 
     def _ufl_hash_data_(self):
-        return (self._geometric_dimension, self._topological_dimension, self._cellname)
+        return (self._geometric_dimension, self._topological_dimension,
+                self._cellname)
 
+
+# @six.python_2_unicode_compatible
 @attach_operators_from_hash_data
 class TensorProductCell(AbstractCell):
-    __slots__ = ("_cells",)
-    def __init__(self, cells):
+    __slots__ = as_native_strings(("_cells",))
+
+    def __init__(self, *cells, **kwargs):
+        keywords = list(kwargs.keys())
+        if keywords and keywords != ["geometric_dimension"]:
+            raise ValueError(
+                "TensorProductCell got an unexpected keyword argument '%s'" %
+                keywords[0])
+
         self._cells = tuple(as_cell(cell) for cell in cells)
 
-        gdims = [cell.geometric_dimension() for cell in self._cells]
-        tdims = [cell.topological_dimension() for cell in self._cells]
-        gdim = sum(gdims)
-        tdim = sum(tdims)
+        tdim = sum([cell.topological_dimension() for cell in self._cells])
+        if kwargs:
+            gdim = kwargs["geometric_dimension"]
+        else:
+            gdim = sum([cell.geometric_dimension() for cell in self._cells])
 
         AbstractCell.__init__(self, tdim, gdim)
 
+    def cellname(self):
+        "Return the cellname of the cell."
+        return " * ".join([cell._cellname for cell in self._cells])
+
+    def reconstruct(self, geometric_dimension=None):
+        if geometric_dimension is None:
+            geometric_dimension = self._geometric_dimension
+        return TensorProductCell(*(self._cells), geometric_dimension=geometric_dimension)
+
     def is_simplex(self):
         "Return True if this is a simplex cell."
         if len(self._cells) == 1:
@@ -218,7 +259,7 @@ class TensorProductCell(AbstractCell):
 
     def num_vertices(self):
         "The number of cell vertices."
-        return product(c.num_vertices() for c in self._cells)
+        return reduce(lambda x, y: x * y, [c.num_vertices() for c in self._cells])
 
     def num_edges(self):
         "The number of cell edges."
@@ -233,107 +274,51 @@ class TensorProductCell(AbstractCell):
         return self._cells
 
     def __str__(self):
-        return repr(self)
-
-    def __repr__(self):
-        return "TensorProductCell(%s)" % ", ".join(repr(c) for c in self._cells)
-
-    def _ufl_hash_data_(self):
-        return tuple(c._ufl_hash_data_() for c in self._cells)
-
-
- at attach_operators_from_hash_data
-class OuterProductCell(AbstractCell): # TODO: Remove this and use TensorProductCell instead
-    """Representation of a cell formed as the Cartesian product of
-    two existing cells"""
-    __slots__ = ("_A", "_B", "facet_horiz", "facet_vert")
-
-    def __init__(self, A, B, gdim=None):
-        self._A = A
-        self._B = B
-
-        tdim = A.topological_dimension() + B.topological_dimension()
-        # default gdim -- "only as big as it needs to be, but not smaller than A or B"
-        gdim_temp = max(A.geometric_dimension(),
-                        B.geometric_dimension(),
-                        A.topological_dimension() + B.topological_dimension())
-        if gdim is None:
-            # default gdim
-            gdim = gdim_temp
+        gdim = self.geometric_dimension()
+        tdim = self.topological_dimension()
+        reprs = ", ".join(repr(c) for c in self._cells)
+        if gdim == tdim:
+            gdimstr = ""
         else:
-            # otherwise, validate custom gdim
-            if not isinstance(gdim, int):
-                raise TypeError("gdim must be an integer")
-            if gdim < gdim_temp:
-                raise ValueError("gdim must be at least %d" % gdim_temp)
-
-        AbstractCell.__init__(self, tdim, gdim)
-
-        # facets for extruded cells
-        if B.cellname() == "interval":
-            self.facet_horiz = A
-            if A.topological_dimension() == 2:
-                self.facet_vert = OuterProductCell(Cell("interval"), Cell("interval"))
-            elif A.topological_dimension() == 1:
-                # Terminate this recursion somewhere!
-                self.facet_vert = Cell("interval")
-            else:
-                # Don't know how to extrude this
-                self.facet_vert = None
-
-    def is_simplex(self):
-        "Return True if this is a simplex cell."
-        return False
-
-    def has_simplex_facets(self):
-        "Return True if all the facets of this cell are simplex cells."
-        # Actually sometimes true
-        return False
-
-    def num_vertices(self):
-        "The number of cell vertices."
-        return self._A.num_vertices() * self._B.num_vertices()
-
-    def num_edges(self):
-        "The number of cell edges."
-        error("Not defined for OuterProductCell.")
-
-    def num_facets(self):
-        "The number of cell facets."
-        return self._A.num_facets() + self._B.num_facets()
+            gdimstr = ", geometric_dimension=%d" % gdim
+        r = "TensorProductCell(%s%s)" % (reprs, gdimstr)
+        return r
 
     def __repr__(self):
-        return "OuterProductCell(*%r)" % list([self._A, self._B])
+        return str(self)
 
     def _ufl_hash_data_(self):
-        return tuple(c._ufl_hash_data_() for c in (self._A, self._B))
+        return tuple(c._ufl_hash_data_() for c in self._cells) + (self._geometric_dimension,)
 
 
 # --- Utility conversion functions
 
-# Mapping from topological dimension to reference cell name for simplices
-_simplex_dim2cellname = {
-    0: "vertex",
-    1: "interval",
-    2: "triangle",
-    3: "tetrahedron",
-    }
-
-# Mapping from topological dimension to reference cell name for hypercubes
-_hypercube_dim2cellname = {
-    0: "vertex",
-    1: "interval",
-    2: "quadrilateral",
-    3: "hexahedron",
-    }
+# Mapping from topological dimension to reference cell name for
+# simplices
+_simplex_dim2cellname = {0: "vertex",
+                         1: "interval",
+                         2: "triangle",
+                         3: "tetrahedron"}
+
+# Mapping from topological dimension to reference cell name for
+# hypercubes
+_hypercube_dim2cellname = {0: "vertex",
+                           1: "interval",
+                           2: "quadrilateral",
+                           3: "hexahedron"}
+
 
 def simplex(topological_dimension, geometric_dimension=None):
     "Return a simplex cell of given dimension."
-    return Cell(_simplex_dim2cellname[topological_dimension], geometric_dimension)
+    return Cell(_simplex_dim2cellname[topological_dimension],
+                geometric_dimension)
+
 
 def hypercube(topological_dimension, geometric_dimension=None):
     "Return a hypercube cell of given dimension."
-    return Cell(_hypercube_dim2cellname[topological_dimension], geometric_dimension)
+    return Cell(_hypercube_dim2cellname[topological_dimension],
+                geometric_dimension)
+
 
 def as_cell(cell):
     """Convert any valid object to a Cell or return cell if it is already a Cell.
@@ -342,7 +327,7 @@ def as_cell(cell):
     """
     if isinstance(cell, AbstractCell):
         return cell
-    elif isinstance(cell, str):
+    elif isinstance(cell, string_types):
         return Cell(cell)
     elif isinstance(cell, tuple):
         return TensorProductCell(cell)
diff --git a/ufl/checks.py b/ufl/checks.py
index e40cc5e..17fbf52 100644
--- a/ufl/checks.py
+++ b/ufl/checks.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Utility functions for checking properties of expressions."""
 
-# Copyright (C) 2013-2015 Martin Sandve Alnæs
+# Copyright (C) 2013-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -23,39 +23,46 @@
 from ufl.core.expr import Expr
 from ufl.corealg.traversal import traverse_unique_terminals
 
+
 def is_python_scalar(expression):
     "Return True iff expression is of a Python scalar type."
     return isinstance(expression, (int, float))
 
+
 def is_ufl_scalar(expression):
     """Return True iff expression is scalar-valued,
     but possibly containing free indices."""
     return isinstance(expression, Expr) and not expression.ufl_shape
 
+
 def is_true_ufl_scalar(expression):
     """Return True iff expression is scalar-valued,
     with no free indices."""
     return isinstance(expression, Expr) and \
         not (expression.ufl_shape or expression.ufl_free_indices)
 
+
 def is_cellwise_constant(expr):
     "Return whether expression is constant over a single cell."
     # TODO: Implement more accurately considering e.g. derivatives?
     return all(t.is_cellwise_constant() for t in traverse_unique_terminals(expr))
 
+
 def is_globally_constant(expr):
     """Check if an expression is globally constant, which
     includes spatially independent constant coefficients that
     are not known before assembly time."""
-    # TODO: This does not consider gradients of coefficients, so false negatives are possible.
-    #from ufl.argument import Argument
-    #from ufl.coefficient import Coefficient
+    # TODO: This does not consider gradients of coefficients, so false
+    # negatives are possible.
+    # from ufl.argument import Argument
+    # from ufl.coefficient import Coefficient
     from ufl.geometry import GeometricQuantity
     from ufl.core.terminal import FormArgument
     for e in traverse_unique_terminals(expr):
         # Return False if any single terminal is not constant
         if e._ufl_is_literal_:
-            # Accept literals first, they are the most common terminals
+            # Accept literals first, they are the most common
+            # terminals
             continue
         elif isinstance(e, FormArgument):
             # Accept only Real valued Arguments and Coefficients
@@ -64,12 +71,14 @@ def is_globally_constant(expr):
             else:
                 return False
         elif isinstance(e, GeometricQuantity):
-            # Reject all geometric quantities, they all vary over cells
+            # Reject all geometric quantities, they all vary over
+            # cells
             return False
 
     # All terminals passed constant check
     return True
 
+
 def is_scalar_constant_expression(expr):
     """Check if an expression is a globally constant scalar expression."""
     if is_python_scalar(expr):
diff --git a/ufl/classes.py b/ufl/classes.py
index c63587d..521eb22 100644
--- a/ufl/classes.py
+++ b/ufl/classes.py
@@ -1,11 +1,12 @@
 # -*- coding: utf-8 -*-
+# flake8: noqa
 """This file is useful for external code like tests and form compilers,
 since it enables the syntax "from ufl.classes import CellFacetooBar" for getting
 implementation details not exposed through the default ufl namespace.
 It also contains functionality used by algorithms for dealing with groups
 of classes, and for mapping types to different handler functions."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -26,15 +27,13 @@ of classes, and for mapping types to different handler functions."""
 # Modified by Kristian B. Oelgaard, 2011
 # Modified by Andrew T. T. McRae, 2014
 
-
 # This will be populated part by part below
 __all__ = []
 
+from ufl.utils.py23 import as_native_strings
 
-#
-# Import all submodules, triggering execution of the
-# ufl_type class decorator for each Expr class.
-#
+# Import all submodules, triggering execution of the ufl_type class
+# decorator for each Expr class.
 
 # Base classes of Expr type hierarchy
 import ufl.core.expr
@@ -46,7 +45,6 @@ import ufl.constantvalue
 import ufl.argument
 import ufl.coefficient
 import ufl.geometry
-import ufl.indexing
 
 # Operator types
 import ufl.indexed
@@ -62,19 +60,17 @@ import ufl.restriction
 import ufl.exprcontainers
 import ufl.referencevalue
 
-# Make sure we import exproperators which attaches special functions to Expr
+# Make sure we import exproperators which attaches special functions
+# to Expr
 from ufl import exproperators as __exproperators
 
-
-#
 # Make sure to import modules with new Expr subclasses here!
-#
 
 # Collect all classes in sets automatically classified by some properties
-all_ufl_classes     = set(ufl.core.expr.Expr._ufl_all_classes_)
-abstract_classes    = set(c for c in all_ufl_classes if c._ufl_is_abstract_)
-ufl_classes         = set(c for c in all_ufl_classes if not c._ufl_is_abstract_)
-terminal_classes    = set(c for c in all_ufl_classes if c._ufl_is_terminal_)
+all_ufl_classes = set(ufl.core.expr.Expr._ufl_all_classes_)
+abstract_classes = set(c for c in all_ufl_classes if c._ufl_is_abstract_)
+ufl_classes = set(c for c in all_ufl_classes if not c._ufl_is_abstract_)
+terminal_classes = set(c for c in all_ufl_classes if c._ufl_is_terminal_)
 nonterminal_classes = set(c for c in all_ufl_classes if not c._ufl_is_terminal_)
 
 __all__ += [
@@ -83,7 +79,8 @@ __all__ += [
     "ufl_classes",
     "terminal_classes",
     "nonterminal_classes",
-    ]
+]
+
 
 def populate_namespace_with_expr_classes(namespace):
     """Export all Expr subclasses into the namespace under their natural name."""
@@ -95,12 +92,11 @@ def populate_namespace_with_expr_classes(namespace):
         names.append(class_name)
     return names
 
+
 __all__ += populate_namespace_with_expr_classes(locals())
 
 
-#
 # Semi-automated imports of non-expr classes:
-#
 
 def populate_namespace_with_module_classes(mod, loc):
     """Export the classes that submodules list in __all_classes__."""
@@ -109,32 +105,36 @@ def populate_namespace_with_module_classes(mod, loc):
         loc[name] = getattr(mod, name)
     return names
 
-import ufl.cell
+
+import ufl.cell  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.cell, locals())
 
-import ufl.finiteelement
+import ufl.finiteelement  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.finiteelement, locals())
 
-import ufl.domain
+import ufl.domain  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.domain, locals())
 
-import ufl.functionspace
+import ufl.functionspace  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.functionspace, locals())
 
-import ufl.core.multiindex
+import ufl.core.multiindex  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.core.multiindex, locals())
 
-import ufl.argument
+import ufl.argument  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.argument, locals())
 
-import ufl.measure
+import ufl.measure  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.measure, locals())
 
-import ufl.integral
+import ufl.integral  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.integral, locals())
 
-import ufl.form
+import ufl.form  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.form, locals())
 
-import ufl.equation
+import ufl.equation  # noqa E401
 __all__ += populate_namespace_with_module_classes(ufl.equation, locals())
+
+
+__all__ = as_native_strings(__all__)
diff --git a/ufl/coefficient.py b/ufl/coefficient.py
index 0356f49..414ef87 100644
--- a/ufl/coefficient.py
+++ b/ufl/coefficient.py
@@ -2,7 +2,7 @@
 """This module defines the Coefficient class and a number
 of related classes, including Constant."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,11 +20,12 @@ of related classes, including Constant."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2008-2009.
+# Modified by Massimiliano Leoni, 2016.
 
-from ufl.log import deprecate
-from ufl.assertions import ufl_assert
+from ufl.utils.py23 import as_native_str
+from ufl.log import error
 from ufl.core.ufl_type import ufl_type
-from ufl.core.terminal import Terminal, FormArgument
+from ufl.core.terminal import FormArgument
 from ufl.finiteelement import FiniteElementBase, FiniteElement, VectorElement, TensorElement
 from ufl.domain import as_domain, default_domain
 from ufl.functionspace import AbstractFunctionSpace, FunctionSpace
@@ -33,12 +34,14 @@ from ufl.utils.counted import counted_init
 
 # --- The Coefficient class represents a coefficient in a form ---
 
+
 @ufl_type()
 class Coefficient(FormArgument):
     """UFL form argument type: Representation of a form coefficient."""
 
-    # Slots are disabled here because they cause trouble in PyDOLFIN multiple inheritance pattern:
-    #__slots__ = ("_count", "_ufl_function_space", "_repr", "_ufl_shape")
+    # Slots are disabled here because they cause trouble in PyDOLFIN
+    # multiple inheritance pattern:
+    # __slots__ = ("_count", "_ufl_function_space", "_repr", "_ufl_shape")
     _ufl_noslots_ = True
     _globalcount = 0
 
@@ -47,7 +50,8 @@ class Coefficient(FormArgument):
         counted_init(self, count, Coefficient)
 
         if isinstance(function_space, FiniteElementBase):
-            # For legacy support for .ufl files using cells, we map the cell to The Default Mesh
+            # For legacy support for .ufl files using cells, we map
+            # the cell to The Default Mesh
             element = function_space
             domain = default_domain(element.cell())
             function_space = FunctionSpace(domain, element)
@@ -57,13 +61,15 @@ class Coefficient(FormArgument):
         self._ufl_function_space = function_space
         self._ufl_shape = function_space.ufl_element().value_shape()
 
-        self._repr = "Coefficient(%r, %r)" % (self._ufl_function_space, self._count)
+        self._repr = as_native_str("Coefficient(%s, %s)" % (
+            repr(self._ufl_function_space), repr(self._count)))
 
     def count(self):
         return self._count
 
     @property
     def ufl_shape(self):
+        "Return the associated UFL shape."
         return self._ufl_shape
 
     def ufl_function_space(self):
@@ -78,9 +84,10 @@ class Coefficient(FormArgument):
         "Shortcut to get the finite element of the function space of this coefficient."
         return self._ufl_function_space.ufl_element()
 
-    def element(self):
-        deprecate("Coefficient.element() is deprecated, please use Coefficient.ufl_element() instead.")
-        return self.ufl_element()
+    # def element(self):
+    #    "Deprecated, please use Coefficient.ufl_element() instead."
+    #    deprecate("Coefficient.element() is deprecated, please use Coefficient.ufl_element() instead.")
+    #    return self.ufl_element()
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
@@ -114,7 +121,9 @@ class Coefficient(FormArgument):
         return (self._count == other._count and
                 self._ufl_function_space == other._ufl_function_space)
 
-# --- Helper functions for defining constant coefficients without specifying element ---
+
+# --- Helper functions for defining constant coefficients without
+# --- specifying element ---
 
 def Constant(domain, count=None):
     """UFL value: Represents a globally constant scalar valued coefficient."""
@@ -123,6 +132,7 @@ def Constant(domain, count=None):
     fs = FunctionSpace(domain, element)
     return Coefficient(fs, count=count)
 
+
 def VectorConstant(domain, dim=None, count=None):
     """UFL value: Represents a globally constant vector valued coefficient."""
     domain = as_domain(domain)
@@ -130,13 +140,16 @@ def VectorConstant(domain, dim=None, count=None):
     fs = FunctionSpace(domain, element)
     return Coefficient(fs, count=count)
 
+
 def TensorConstant(domain, shape=None, symmetry=None, count=None):
     """UFL value: Represents a globally constant tensor valued coefficient."""
     domain = as_domain(domain)
-    element = TensorElement("Real", domain.ufl_cell(), 0, shape=shape, symmetry=symmetry)
+    element = TensorElement("Real", domain.ufl_cell(), 0, shape=shape,
+                            symmetry=symmetry)
     fs = FunctionSpace(domain, element)
     return Coefficient(fs, count=count)
 
+
 # --- Helper functions for subfunctions on mixed elements ---
 
 def Coefficients(function_space):
diff --git a/ufl/compound_expressions.py b/ufl/compound_expressions.py
index 00b5512..1587c68 100644
--- a/ufl/compound_expressions.py
+++ b/ufl/compound_expressions.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Functions implementing compound expressions as equivalent representations using basic operators."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -20,8 +20,7 @@
 #
 # Modified by Anders Logg, 2009-2010
 
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
+from ufl.log import error
 from ufl.core.multiindex import indices, Index
 from ufl.tensors import as_tensor, as_matrix, as_vector
 from ufl.operators import sqrt
@@ -31,40 +30,45 @@ from ufl.operators import sqrt
 # deviatoric parts below were created with the script
 # tensoralgebrastrings.py under sandbox/scripts/
 
-
 # Note: Avoiding or delaying application of these horrible expressions
 # would be a major improvement to UFL and the form compiler toolchain.
-# It could easily be a moderate to major undertaking to get rid of though.
+# It could easily be a moderate to major undertaking to get rid of
+# though.
+
 
 def cross_expr(a, b):
     assert len(a) == 3
     assert len(b) == 3
+
     def c(i, j):
         return a[i]*b[j] - a[j]*b[i]
     return as_vector((c(1, 2), c(2, 0), c(0, 1)))
 
+
 def generic_pseudo_determinant_expr(A):
     """Compute the pseudo-determinant of A: sqrt(det(A.T*A))."""
     i, j, k = indices(3)
     ATA = as_tensor(A[k, i]*A[k, j], (i, j))
     return sqrt(determinant_expr(ATA))
 
+
 def pseudo_determinant_expr(A):
     """Compute the pseudo-determinant of A."""
     m, n = A.ufl_shape
     if n == 1:
         # Special case 1xm for simpler expression
         i = Index()
-        return sqrt(A[i,0]*A[i,0])
+        return sqrt(A[i, 0]*A[i, 0])
     elif n == 2 and m == 3:
         # Special case 2x3 for simpler expression
-        c = cross_expr(A[:,0], A[:,1])
+        c = cross_expr(A[:, 0], A[:, 1])
         i = Index()
         return sqrt(c[i]*c[i])
     else:
         # Generic formulation based on A.T*A
         return generic_pseudo_determinant_expr(A)
 
+
 def generic_pseudo_inverse_expr(A):
     """Compute the Penrose-Moore pseudo-inverse of A: (A.T*A)^-1 * A.T."""
     i, j, k = indices(3)
@@ -73,13 +77,14 @@ def generic_pseudo_inverse_expr(A):
     q, r, s = indices(3)
     return as_tensor(ATAinv[r, q] * A[s, q], (r, s))
 
+
 def pseudo_inverse_expr(A):
     """Compute the Penrose-Moore pseudo-inverse of A: (A.T*A)^-1 * A.T."""
     m, n = A.ufl_shape
     if n == 1:
         # Simpler special case for 1d
         i, j, k = indices(3)
-        return as_tensor(A[i,j], (j,i)) / (A[k,0]*A[k,0])
+        return as_tensor(A[i, j], (j, i)) / (A[k, 0]*A[k, 0])
     else:
         # Generic formulation
         return generic_pseudo_inverse_expr(A)
@@ -103,19 +108,24 @@ def determinant_expr(A):
     # TODO: Implement generally for all dimensions?
     error("determinant_expr not implemented for shape %s." % (sh,))
 
+
 def _det_2x2(B, i, j, k, l):
     return B[i, k]*B[j, l] - B[i, l]*B[j, k]
 
+
 def determinant_expr_2x2(B):
     return _det_2x2(B, 0, 1, 0, 1)
 
+
 def old_determinant_expr_3x3(A):
     return (A[0, 0]*_det_2x2(A, 1, 2, 1, 2) +
             A[0, 1]*_det_2x2(A, 1, 2, 2, 0) +
             A[0, 2]*_det_2x2(A, 1, 2, 0, 1))
 
+
 def determinant_expr_3x3(A):
-    return codeterminant_expr_nxn(A, [0,1,2], [0,1,2])
+    return codeterminant_expr_nxn(A, [0, 1, 2], [0, 1, 2])
+
 
 def codeterminant_expr_nxn(A, rows, cols):
     if len(rows) == 2:
@@ -128,6 +138,7 @@ def codeterminant_expr_nxn(A, rows, cols):
         codet += A[r, c] * codeterminant_expr_nxn(A, subrows, subcols)
     return codet
 
+
 def inverse_expr(A):
     "Compute the inverse of A."
     sh = A.ufl_shape
@@ -141,9 +152,11 @@ def inverse_expr(A):
     else:
         return pseudo_inverse_expr(A)
 
+
 def adj_expr(A):
     sh = A.ufl_shape
-    ufl_assert(sh[0] == sh[1], "Expecting square matrix.")
+    if sh[0] != sh[1]:
+        error("Expecting square matrix.")
 
     if sh[0] == 2:
         return adj_expr_2x2(A)
@@ -154,41 +167,45 @@ def adj_expr(A):
 
     error("adj_expr not implemented for dimension %s." % sh[0])
 
+
 def adj_expr_2x2(A):
     return as_matrix([[A[1, 1], -A[0, 1]],
                       [-A[1, 0], A[0, 0]]])
 
+
 def adj_expr_3x3(A):
     return as_matrix([
-        [ A[2, 2]*A[1, 1] - A[1, 2]*A[2, 1],   -A[0, 1]*A[2, 2] + A[0, 2]*A[2, 1],   A[0, 1]*A[1, 2] - A[0, 2]*A[1, 1]],
-        [-A[2, 2]*A[1, 0] + A[1, 2]*A[2, 0],   -A[0, 2]*A[2, 0] + A[2, 2]*A[0, 0],   A[0, 2]*A[1, 0] - A[1, 2]*A[0, 0]],
-        [ A[1, 0]*A[2, 1] - A[2, 0]*A[1, 1],    A[0, 1]*A[2, 0] - A[0, 0]*A[2, 1],   A[0, 0]*A[1, 1] - A[0, 1]*A[1, 0]],
-        ])
+        [A[2, 2]*A[1, 1] - A[1, 2]*A[2, 1], -A[0, 1]*A[2, 2] + A[0, 2]*A[2, 1], A[0, 1]*A[1, 2] - A[0, 2]*A[1, 1]],
+        [-A[2, 2]*A[1, 0] + A[1, 2]*A[2, 0], -A[0, 2]*A[2, 0] + A[2, 2]*A[0, 0], A[0, 2]*A[1, 0] - A[1, 2]*A[0, 0]],
+        [A[1, 0]*A[2, 1] - A[2, 0]*A[1, 1], A[0, 1]*A[2, 0] - A[0, 0]*A[2, 1], A[0, 0]*A[1, 1] - A[0, 1]*A[1, 0]],
+    ])
+
 
 def adj_expr_4x4(A):
     return as_matrix([
         [-A[3, 3]*A[2, 1]*A[1, 2] + A[1, 2]*A[3, 1]*A[2, 3] + A[1, 1]*A[3, 3]*A[2, 2] - A[3, 1]*A[2, 2]*A[1, 3] + A[2, 1]*A[1, 3]*A[3, 2] - A[1, 1]*A[3, 2]*A[2, 3],
          -A[3, 1]*A[0, 2]*A[2, 3] + A[0, 1]*A[3, 2]*A[2, 3] - A[0, 3]*A[2, 1]*A[3, 2] + A[3, 3]*A[2, 1]*A[0, 2] - A[3, 3]*A[0, 1]*A[2, 2] + A[0, 3]*A[3, 1]*A[2, 2],
-          A[3, 1]*A[1, 3]*A[0, 2] + A[1, 1]*A[0, 3]*A[3, 2] - A[0, 3]*A[1, 2]*A[3, 1] - A[0, 1]*A[1, 3]*A[3, 2] + A[3, 3]*A[1, 2]*A[0, 1] - A[1, 1]*A[3, 3]*A[0, 2],
-          A[1, 1]*A[0, 2]*A[2, 3] - A[2, 1]*A[1, 3]*A[0, 2] + A[0, 3]*A[2, 1]*A[1, 2] - A[1, 2]*A[0, 1]*A[2, 3] - A[1, 1]*A[0, 3]*A[2, 2] + A[0, 1]*A[2, 2]*A[1, 3]],
-        [ A[3, 3]*A[1, 2]*A[2, 0] - A[3, 0]*A[1, 2]*A[2, 3] + A[1, 0]*A[3, 2]*A[2, 3] - A[3, 3]*A[1, 0]*A[2, 2] - A[1, 3]*A[3, 2]*A[2, 0] + A[3, 0]*A[2, 2]*A[1, 3],
-          A[0, 3]*A[3, 2]*A[2, 0] - A[0, 3]*A[3, 0]*A[2, 2] + A[3, 3]*A[0, 0]*A[2, 2] + A[3, 0]*A[0, 2]*A[2, 3] - A[0, 0]*A[3, 2]*A[2, 3] - A[3, 3]*A[0, 2]*A[2, 0],
+         A[3, 1]*A[1, 3]*A[0, 2] + A[1, 1]*A[0, 3]*A[3, 2] - A[0, 3]*A[1, 2]*A[3, 1] - A[0, 1]*A[1, 3]*A[3, 2] + A[3, 3]*A[1, 2]*A[0, 1] - A[1, 1]*A[3, 3]*A[0, 2],
+         A[1, 1]*A[0, 2]*A[2, 3] - A[2, 1]*A[1, 3]*A[0, 2] + A[0, 3]*A[2, 1]*A[1, 2] - A[1, 2]*A[0, 1]*A[2, 3] - A[1, 1]*A[0, 3]*A[2, 2] + A[0, 1]*A[2, 2]*A[1, 3]],
+        [A[3, 3]*A[1, 2]*A[2, 0] - A[3, 0]*A[1, 2]*A[2, 3] + A[1, 0]*A[3, 2]*A[2, 3] - A[3, 3]*A[1, 0]*A[2, 2] - A[1, 3]*A[3, 2]*A[2, 0] + A[3, 0]*A[2, 2]*A[1, 3],
+         A[0, 3]*A[3, 2]*A[2, 0] - A[0, 3]*A[3, 0]*A[2, 2] + A[3, 3]*A[0, 0]*A[2, 2] + A[3, 0]*A[0, 2]*A[2, 3] - A[0, 0]*A[3, 2]*A[2, 3] - A[3, 3]*A[0, 2]*A[2, 0],
          -A[3, 3]*A[0, 0]*A[1, 2] + A[0, 0]*A[1, 3]*A[3, 2] - A[3, 0]*A[1, 3]*A[0, 2] + A[3, 3]*A[1, 0]*A[0, 2] + A[0, 3]*A[3, 0]*A[1, 2] - A[0, 3]*A[1, 0]*A[3, 2],
-          A[0, 3]*A[1, 0]*A[2, 2] + A[1, 3]*A[0, 2]*A[2, 0] - A[0, 0]*A[2, 2]*A[1, 3] - A[0, 3]*A[1, 2]*A[2, 0] + A[0, 0]*A[1, 2]*A[2, 3] - A[1, 0]*A[0, 2]*A[2, 3]],
-        [ A[3, 1]*A[1, 3]*A[2, 0] + A[3, 3]*A[2, 1]*A[1, 0] + A[1, 1]*A[3, 0]*A[2, 3] - A[1, 0]*A[3, 1]*A[2, 3] - A[3, 0]*A[2, 1]*A[1, 3] - A[1, 1]*A[3, 3]*A[2, 0],
-          A[3, 3]*A[0, 1]*A[2, 0] - A[3, 3]*A[0, 0]*A[2, 1] - A[0, 3]*A[3, 1]*A[2, 0] - A[3, 0]*A[0, 1]*A[2, 3] + A[0, 0]*A[3, 1]*A[2, 3] + A[0, 3]*A[3, 0]*A[2, 1],
+         A[0, 3]*A[1, 0]*A[2, 2] + A[1, 3]*A[0, 2]*A[2, 0] - A[0, 0]*A[2, 2]*A[1, 3] - A[0, 3]*A[1, 2]*A[2, 0] + A[0, 0]*A[1, 2]*A[2, 3] - A[1, 0]*A[0, 2]*A[2, 3]],
+        [A[3, 1]*A[1, 3]*A[2, 0] + A[3, 3]*A[2, 1]*A[1, 0] + A[1, 1]*A[3, 0]*A[2, 3] - A[1, 0]*A[3, 1]*A[2, 3] - A[3, 0]*A[2, 1]*A[1, 3] - A[1, 1]*A[3, 3]*A[2, 0],
+         A[3, 3]*A[0, 1]*A[2, 0] - A[3, 3]*A[0, 0]*A[2, 1] - A[0, 3]*A[3, 1]*A[2, 0] - A[3, 0]*A[0, 1]*A[2, 3] + A[0, 0]*A[3, 1]*A[2, 3] + A[0, 3]*A[3, 0]*A[2, 1],
          -A[0, 0]*A[3, 1]*A[1, 3] + A[0, 3]*A[1, 0]*A[3, 1] - A[3, 3]*A[1, 0]*A[0, 1] + A[1, 1]*A[3, 3]*A[0, 0] - A[1, 1]*A[0, 3]*A[3, 0] + A[3, 0]*A[0, 1]*A[1, 3],
-          A[0, 0]*A[2, 1]*A[1, 3] + A[1, 0]*A[0, 1]*A[2, 3] - A[0, 3]*A[2, 1]*A[1, 0] + A[1, 1]*A[0, 3]*A[2, 0] - A[1, 1]*A[0, 0]*A[2, 3] - A[0, 1]*A[1, 3]*A[2, 0]],
+         A[0, 0]*A[2, 1]*A[1, 3] + A[1, 0]*A[0, 1]*A[2, 3] - A[0, 3]*A[2, 1]*A[1, 0] + A[1, 1]*A[0, 3]*A[2, 0] - A[1, 1]*A[0, 0]*A[2, 3] - A[0, 1]*A[1, 3]*A[2, 0]],
         [-A[1, 2]*A[3, 1]*A[2, 0] - A[2, 1]*A[1, 0]*A[3, 2] + A[3, 0]*A[2, 1]*A[1, 2] - A[1, 1]*A[3, 0]*A[2, 2] + A[1, 0]*A[3, 1]*A[2, 2] + A[1, 1]*A[3, 2]*A[2, 0],
          -A[3, 0]*A[2, 1]*A[0, 2] - A[0, 1]*A[3, 2]*A[2, 0] + A[3, 1]*A[0, 2]*A[2, 0] - A[0, 0]*A[3, 1]*A[2, 2] + A[3, 0]*A[0, 1]*A[2, 2] + A[0, 0]*A[2, 1]*A[3, 2],
-          A[0, 0]*A[1, 2]*A[3, 1] - A[1, 0]*A[3, 1]*A[0, 2] + A[1, 1]*A[3, 0]*A[0, 2] + A[1, 0]*A[0, 1]*A[3, 2] - A[3, 0]*A[1, 2]*A[0, 1] - A[1, 1]*A[0, 0]*A[3, 2],
+         A[0, 0]*A[1, 2]*A[3, 1] - A[1, 0]*A[3, 1]*A[0, 2] + A[1, 1]*A[3, 0]*A[0, 2] + A[1, 0]*A[0, 1]*A[3, 2] - A[3, 0]*A[1, 2]*A[0, 1] - A[1, 1]*A[0, 0]*A[3, 2],
          -A[1, 1]*A[0, 2]*A[2, 0] + A[2, 1]*A[1, 0]*A[0, 2] + A[1, 2]*A[0, 1]*A[2, 0] + A[1, 1]*A[0, 0]*A[2, 2] - A[1, 0]*A[0, 1]*A[2, 2] - A[0, 0]*A[2, 1]*A[1, 2]],
-        ])
+    ])
 
 
 def cofactor_expr(A):
     sh = A.ufl_shape
-    ufl_assert(sh[0] == sh[1], "Expecting square matrix.")
+    if sh[0] != sh[1]:
+        error("Expecting square matrix.")
 
     if sh[0] == 2:
         return cofactor_expr_2x2(A)
@@ -199,41 +216,45 @@ def cofactor_expr(A):
 
     error("cofactor_expr not implemented for dimension %s." % sh[0])
 
+
 def cofactor_expr_2x2(A):
     return as_matrix([[A[1, 1], -A[1, 0]],
                       [-A[0, 1], A[0, 0]]])
 
+
 def cofactor_expr_3x3(A):
     return as_matrix([
         [A[1, 1]*A[2, 2] - A[2, 1]*A[1, 2], A[2, 0]*A[1, 2] - A[1, 0]*A[2, 2], - A[2, 0]*A[1, 1] + A[1, 0]*A[2, 1]],
         [A[2, 1]*A[0, 2] - A[0, 1]*A[2, 2], A[0, 0]*A[2, 2] - A[2, 0]*A[0, 2], - A[0, 0]*A[2, 1] + A[2, 0]*A[0, 1]],
         [A[0, 1]*A[1, 2] - A[1, 1]*A[0, 2], A[1, 0]*A[0, 2] - A[0, 0]*A[1, 2], - A[1, 0]*A[0, 1] + A[0, 0]*A[1, 1]],
-        ])
+    ])
+
 
 def cofactor_expr_4x4(A):
     return as_matrix([
         [-A[3, 1]*A[2, 2]*A[1, 3] - A[3, 2]*A[2, 3]*A[1, 1] + A[1, 3]*A[3, 2]*A[2, 1] + A[3, 1]*A[2, 3]*A[1, 2] + A[2, 2]*A[1, 1]*A[3, 3] - A[3, 3]*A[2, 1]*A[1, 2],
          -A[1, 0]*A[2, 2]*A[3, 3] + A[2, 0]*A[3, 3]*A[1, 2] + A[2, 2]*A[1, 3]*A[3, 0] - A[2, 3]*A[3, 0]*A[1, 2] + A[1, 0]*A[3, 2]*A[2, 3] - A[1, 3]*A[3, 2]*A[2, 0],
-          A[1, 0]*A[3, 3]*A[2, 1] + A[2, 3]*A[1, 1]*A[3, 0] - A[2, 0]*A[1, 1]*A[3, 3] - A[1, 3]*A[3, 0]*A[2, 1] - A[1, 0]*A[3, 1]*A[2, 3] + A[3, 1]*A[1, 3]*A[2, 0],
-          A[3, 0]*A[2, 1]*A[1, 2] + A[1, 0]*A[3, 1]*A[2, 2] + A[3, 2]*A[2, 0]*A[1, 1] - A[2, 2]*A[1, 1]*A[3, 0] - A[3, 1]*A[2, 0]*A[1, 2] - A[1, 0]*A[3, 2]*A[2, 1]],
-        [ A[3, 1]*A[2, 2]*A[0, 3] + A[0, 2]*A[3, 3]*A[2, 1] + A[0, 1]*A[3, 2]*A[2, 3] - A[3, 1]*A[0, 2]*A[2, 3] - A[0, 1]*A[2, 2]*A[3, 3] - A[3, 2]*A[0, 3]*A[2, 1],
+         A[1, 0]*A[3, 3]*A[2, 1] + A[2, 3]*A[1, 1]*A[3, 0] - A[2, 0]*A[1, 1]*A[3, 3] - A[1, 3]*A[3, 0]*A[2, 1] - A[1, 0]*A[3, 1]*A[2, 3] + A[3, 1]*A[1, 3]*A[2, 0],
+         A[3, 0]*A[2, 1]*A[1, 2] + A[1, 0]*A[3, 1]*A[2, 2] + A[3, 2]*A[2, 0]*A[1, 1] - A[2, 2]*A[1, 1]*A[3, 0] - A[3, 1]*A[2, 0]*A[1, 2] - A[1, 0]*A[3, 2]*A[2, 1]],
+        [A[3, 1]*A[2, 2]*A[0, 3] + A[0, 2]*A[3, 3]*A[2, 1] + A[0, 1]*A[3, 2]*A[2, 3] - A[3, 1]*A[0, 2]*A[2, 3] - A[0, 1]*A[2, 2]*A[3, 3] - A[3, 2]*A[0, 3]*A[2, 1],
          -A[2, 2]*A[0, 3]*A[3, 0] - A[0, 2]*A[2, 0]*A[3, 3] - A[3, 2]*A[2, 3]*A[0, 0] + A[2, 2]*A[3, 3]*A[0, 0] + A[0, 2]*A[2, 3]*A[3, 0] + A[3, 2]*A[2, 0]*A[0, 3],
-          A[3, 1]*A[2, 3]*A[0, 0] - A[0, 1]*A[2, 3]*A[3, 0] - A[3, 1]*A[2, 0]*A[0, 3] - A[3, 3]*A[0, 0]*A[2, 1] + A[0, 3]*A[3, 0]*A[2, 1] + A[0, 1]*A[2, 0]*A[3, 3],
-          A[3, 2]*A[0, 0]*A[2, 1] - A[0, 2]*A[3, 0]*A[2, 1] + A[0, 1]*A[2, 2]*A[3, 0] + A[3, 1]*A[0, 2]*A[2, 0] - A[0, 1]*A[3, 2]*A[2, 0] - A[3, 1]*A[2, 2]*A[0, 0]],
-        [ A[3, 1]*A[1, 3]*A[0, 2] - A[0, 2]*A[1, 1]*A[3, 3] - A[3, 1]*A[0, 3]*A[1, 2] + A[3, 2]*A[1, 1]*A[0, 3] + A[0, 1]*A[3, 3]*A[1, 2] - A[0, 1]*A[1, 3]*A[3, 2],
-          A[1, 3]*A[3, 2]*A[0, 0] - A[1, 0]*A[3, 2]*A[0, 3] - A[1, 3]*A[0, 2]*A[3, 0] + A[0, 3]*A[3, 0]*A[1, 2] + A[1, 0]*A[0, 2]*A[3, 3] - A[3, 3]*A[0, 0]*A[1, 2],
+         A[3, 1]*A[2, 3]*A[0, 0] - A[0, 1]*A[2, 3]*A[3, 0] - A[3, 1]*A[2, 0]*A[0, 3] - A[3, 3]*A[0, 0]*A[2, 1] + A[0, 3]*A[3, 0]*A[2, 1] + A[0, 1]*A[2, 0]*A[3, 3],
+         A[3, 2]*A[0, 0]*A[2, 1] - A[0, 2]*A[3, 0]*A[2, 1] + A[0, 1]*A[2, 2]*A[3, 0] + A[3, 1]*A[0, 2]*A[2, 0] - A[0, 1]*A[3, 2]*A[2, 0] - A[3, 1]*A[2, 2]*A[0, 0]],
+        [A[3, 1]*A[1, 3]*A[0, 2] - A[0, 2]*A[1, 1]*A[3, 3] - A[3, 1]*A[0, 3]*A[1, 2] + A[3, 2]*A[1, 1]*A[0, 3] + A[0, 1]*A[3, 3]*A[1, 2] - A[0, 1]*A[1, 3]*A[3, 2],
+         A[1, 3]*A[3, 2]*A[0, 0] - A[1, 0]*A[3, 2]*A[0, 3] - A[1, 3]*A[0, 2]*A[3, 0] + A[0, 3]*A[3, 0]*A[1, 2] + A[1, 0]*A[0, 2]*A[3, 3] - A[3, 3]*A[0, 0]*A[1, 2],
          -A[1, 0]*A[0, 1]*A[3, 3] + A[0, 1]*A[1, 3]*A[3, 0] - A[3, 1]*A[1, 3]*A[0, 0] - A[1, 1]*A[0, 3]*A[3, 0] + A[1, 0]*A[3, 1]*A[0, 3] + A[1, 1]*A[3, 3]*A[0, 0],
-          A[0, 2]*A[1, 1]*A[3, 0] - A[3, 2]*A[1, 1]*A[0, 0] - A[0, 1]*A[3, 0]*A[1, 2] - A[1, 0]*A[3, 1]*A[0, 2] + A[3, 1]*A[0, 0]*A[1, 2] + A[1, 0]*A[0, 1]*A[3, 2]],
-        [ A[0, 3]*A[2, 1]*A[1, 2] + A[0, 2]*A[2, 3]*A[1, 1] + A[0, 1]*A[2, 2]*A[1, 3] - A[2, 2]*A[1, 1]*A[0, 3] - A[1, 3]*A[0, 2]*A[2, 1] - A[0, 1]*A[2, 3]*A[1, 2],
-          A[1, 0]*A[2, 2]*A[0, 3] + A[1, 3]*A[0, 2]*A[2, 0] - A[1, 0]*A[0, 2]*A[2, 3] - A[2, 0]*A[0, 3]*A[1, 2] - A[2, 2]*A[1, 3]*A[0, 0] + A[2, 3]*A[0, 0]*A[1, 2],
+         A[0, 2]*A[1, 1]*A[3, 0] - A[3, 2]*A[1, 1]*A[0, 0] - A[0, 1]*A[3, 0]*A[1, 2] - A[1, 0]*A[3, 1]*A[0, 2] + A[3, 1]*A[0, 0]*A[1, 2] + A[1, 0]*A[0, 1]*A[3, 2]],
+        [A[0, 3]*A[2, 1]*A[1, 2] + A[0, 2]*A[2, 3]*A[1, 1] + A[0, 1]*A[2, 2]*A[1, 3] - A[2, 2]*A[1, 1]*A[0, 3] - A[1, 3]*A[0, 2]*A[2, 1] - A[0, 1]*A[2, 3]*A[1, 2],
+         A[1, 0]*A[2, 2]*A[0, 3] + A[1, 3]*A[0, 2]*A[2, 0] - A[1, 0]*A[0, 2]*A[2, 3] - A[2, 0]*A[0, 3]*A[1, 2] - A[2, 2]*A[1, 3]*A[0, 0] + A[2, 3]*A[0, 0]*A[1, 2],
          -A[0, 1]*A[1, 3]*A[2, 0] + A[2, 0]*A[1, 1]*A[0, 3] + A[1, 3]*A[0, 0]*A[2, 1] - A[1, 0]*A[0, 3]*A[2, 1] + A[1, 0]*A[0, 1]*A[2, 3] - A[2, 3]*A[1, 1]*A[0, 0],
-          A[1, 0]*A[0, 2]*A[2, 1] - A[0, 2]*A[2, 0]*A[1, 1] + A[0, 1]*A[2, 0]*A[1, 2] + A[2, 2]*A[1, 1]*A[0, 0] - A[1, 0]*A[0, 1]*A[2, 2] - A[0, 0]*A[2, 1]*A[1, 2]]
-        ])
+         A[1, 0]*A[0, 2]*A[2, 1] - A[0, 2]*A[2, 0]*A[1, 1] + A[0, 1]*A[2, 0]*A[1, 2] + A[2, 2]*A[1, 1]*A[0, 0] - A[1, 0]*A[0, 1]*A[2, 2] - A[0, 0]*A[2, 1]*A[1, 2]]
+    ])
 
 
 def deviatoric_expr(A):
     sh = A.ufl_shape
-    ufl_assert(sh[0] == sh[1], "Expecting square matrix.")
+    if sh[0] != sh[1]:
+        error("Expecting square matrix.")
 
     if sh[0] == 2:
         return deviatoric_expr_2x2(A)
@@ -242,11 +263,13 @@ def deviatoric_expr(A):
 
     error("deviatoric_expr not implemented for dimension %s." % sh[0])
 
+
 def deviatoric_expr_2x2(A):
-    return as_matrix([[-1./2*A[1, 1]+1./2*A[0, 0],  A[0, 1]],
-                      [A[1, 0],                    1./2*A[1, 1]-1./2*A[0, 0]]])
+    return as_matrix([[-1./2*A[1, 1]+1./2*A[0, 0], A[0, 1]],
+                      [A[1, 0], 1./2*A[1, 1]-1./2*A[0, 0]]])
+
 
 def deviatoric_expr_3x3(A):
-    return as_matrix([[-1./3*A[1, 1]-1./3*A[2, 2]+2./3*A[0, 0],   A[0, 1],   A[0, 2]],
-                      [A[1, 0],  2./3*A[1, 1]-1./3*A[2, 2]-1./3*A[0, 0],   A[1, 2]],
-                      [A[2, 0],  A[2, 1],   -1./3*A[1, 1]+2./3*A[2, 2]-1./3*A[0, 0]]])
+    return as_matrix([[-1./3*A[1, 1]-1./3*A[2, 2]+2./3*A[0, 0], A[0, 1], A[0, 2]],
+                      [A[1, 0], 2./3*A[1, 1]-1./3*A[2, 2]-1./3*A[0, 0], A[1, 2]],
+                      [A[2, 0], A[2, 1], -1./3*A[1, 1]+2./3*A[2, 2]-1./3*A[0, 0]]])
diff --git a/ufl/conditional.py b/ufl/conditional.py
index faffbb5..352624c 100644
--- a/ufl/conditional.py
+++ b/ufl/conditional.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module defines classes for conditional expressions."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,35 +19,38 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 from ufl.log import warning, error
-from ufl.assertions import ufl_assert
+from ufl.utils.py23 import as_native_strings
+from ufl.core.expr import ufl_err_str
+from ufl.core.ufl_type import ufl_type
 from ufl.core.operator import Operator
 from ufl.constantvalue import as_ufl
 from ufl.precedence import parstr
 from ufl.exprequals import expr_equals
 from ufl.checks import is_true_ufl_scalar
-from ufl.utils.dicts import EmptyDict
-from ufl.core.ufl_type import ufl_type
 
-#--- Condition classes ---
+# --- Condition classes ---
+
+# TODO: Would be nice with some kind of type system to show that this
+# is a boolean type not a float type
 
-# TODO: Would be nice with some kind of type system to show that this is a boolean type not a float type
 
 @ufl_type(is_abstract=True, is_scalar=True)
 class Condition(Operator):
     __slots__ = ()
+
     def __init__(self, operands):
         Operator.__init__(self, operands)
 
     def __bool__(self):
         # Showing explicit error here to protect against misuse
         error("UFL conditions cannot be evaluated as bool in a Python context.")
-        #return NotImplemented
     __nonzero__ = __bool__
 
 
 @ufl_type(is_abstract=True, num_ops=2)
 class BinaryCondition(Condition):
-    __slots__ = ('_name',)
+    __slots__ = as_native_strings(('_name',))
+
     def __init__(self, name, left, right):
         left = as_ufl(left)
         right = as_ufl(right)
@@ -57,34 +60,36 @@ class BinaryCondition(Condition):
         self._name = name
 
         if name in ('!=', '=='):
-            # Since equals and not-equals are used for comparing representations,
-            # we have to allow any shape here. The scalar properties must be
-            # checked when used in conditional instead!
+            # Since equals and not-equals are used for comparing
+            # representations, we have to allow any shape here. The
+            # scalar properties must be checked when used in
+            # conditional instead!
             pass
         elif name in ('&&', '||'):
-            # Binary operators acting on boolean expressions allow only conditions
-            ufl_assert(isinstance(left, Condition),
-                       "Expecting a Condition, not a %s." % left._ufl_class_)
-            ufl_assert(isinstance(right, Condition),
-                       "Expecting a Condition, not a %s." % right._ufl_class_)
+            # Binary operators acting on boolean expressions allow
+            # only conditions
+            for arg in (left, right):
+                if not isinstance(arg, Condition):
+                    error("Expecting a Condition, not %s." % ufl_err_str(arg))
         else:
-            # Binary operators acting on non-boolean expressions allow only scalars
-            ufl_assert(left.ufl_shape == () and right.ufl_shape == (),
-                       "Expecting scalar arguments.")
-            ufl_assert(left.ufl_free_indices == () and right.ufl_free_indices == (),
-                       "Expecting scalar arguments.")
+            # Binary operators acting on non-boolean expressions allow
+            # only scalars
+            if left.ufl_shape != () or right.ufl_shape != ():
+                error("Expecting scalar arguments.")
+            if left.ufl_free_indices != () or right.ufl_free_indices != ():
+                error("Expecting scalar arguments.")
 
     def __str__(self):
-        return "%s %s %s" % (parstr(self.ufl_operands[0], self), self._name, parstr(self.ufl_operands[1], self))
-
-    def __repr__(self):
-        return "%s(%r, %r)" % (type(self).__name__, self.ufl_operands[0], self.ufl_operands[1])
+        return "%s %s %s" % (parstr(self.ufl_operands[0], self),
+                             self._name, parstr(self.ufl_operands[1], self))
 
 
-# Not associating with __eq__, the concept of equality with == is reserved for object equivalence for use in set and dict.
+# Not associating with __eq__, the concept of equality with == is
+# reserved for object equivalence for use in set and dict.
 @ufl_type()
 class EQ(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, "==", left, right)
 
@@ -98,10 +103,12 @@ class EQ(BinaryCondition):
     __nonzero__ = __bool__
 
 
-# Not associating with __ne__, the concept of equality with == is reserved for object equivalence for use in set and dict.
+# Not associating with __ne__, the concept of equality with == is
+# reserved for object equivalence for use in set and dict.
 @ufl_type()
 class NE(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, "!=", left, right)
 
@@ -118,6 +125,7 @@ class NE(BinaryCondition):
 @ufl_type(binop="__le__")
 class LE(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, "<=", left, right)
 
@@ -130,6 +138,7 @@ class LE(BinaryCondition):
 @ufl_type(binop="__ge__")
 class GE(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, ">=", left, right)
 
@@ -138,9 +147,11 @@ class GE(BinaryCondition):
         b = self.ufl_operands[1].evaluate(x, mapping, component, index_values)
         return bool(a >= b)
 
+
 @ufl_type(binop="__lt__")
 class LT(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, "<", left, right)
 
@@ -149,9 +160,11 @@ class LT(BinaryCondition):
         b = self.ufl_operands[1].evaluate(x, mapping, component, index_values)
         return bool(a < b)
 
+
 @ufl_type(binop="__gt__")
 class GT(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, ">", left, right)
 
@@ -160,9 +173,11 @@ class GT(BinaryCondition):
         b = self.ufl_operands[1].evaluate(x, mapping, component, index_values)
         return bool(a > b)
 
+
 @ufl_type()
 class AndCondition(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, "&&", left, right)
 
@@ -171,9 +186,11 @@ class AndCondition(BinaryCondition):
         b = self.ufl_operands[1].evaluate(x, mapping, component, index_values)
         return bool(a and b)
 
+
 @ufl_type()
 class OrCondition(BinaryCondition):
     __slots__ = ()
+
     def __init__(self, left, right):
         BinaryCondition.__init__(self, "||", left, right)
 
@@ -182,13 +199,15 @@ class OrCondition(BinaryCondition):
         b = self.ufl_operands[1].evaluate(x, mapping, component, index_values)
         return bool(a or b)
 
+
 @ufl_type(num_ops=1)
 class NotCondition(Condition):
     __slots__ = ()
 
     def __init__(self, condition):
         Condition.__init__(self, (condition,))
-        ufl_assert(isinstance(condition, Condition), "Expecting a condition.")
+        if not isinstance(condition, Condition):
+            error("Expecting a condition.")
 
     def evaluate(self, x, mapping, component, index_values):
         a = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
@@ -197,32 +216,33 @@ class NotCondition(Condition):
     def __str__(self):
         return "!(%s)" % (str(self.ufl_operands[0]),)
 
-    def __repr__(self):
-        return "NotCondition(%r)" % (self.ufl_operands[0],)
-
 
-#--- Conditional expression (condition ? true_value : false_value) ---
+# --- Conditional expression (condition ? true_value : false_value) ---
 
- at ufl_type(num_ops=3, inherit_shape_from_operand=1, inherit_indices_from_operand=1)
+ at ufl_type(num_ops=3, inherit_shape_from_operand=1,
+          inherit_indices_from_operand=1)
 class Conditional(Operator):
     __slots__ = ()
 
     def __init__(self, condition, true_value, false_value):
-        ufl_assert(isinstance(condition, Condition), "Expectiong condition as first argument.")
+        if not isinstance(condition, Condition):
+            error("Expectiong condition as first argument.")
         true_value = as_ufl(true_value)
         false_value = as_ufl(false_value)
         tsh = true_value.ufl_shape
         fsh = false_value.ufl_shape
-        ufl_assert(tsh == fsh, "Shape mismatch between conditional branches.")
+        if tsh != fsh:
+            error("Shape mismatch between conditional branches.")
         tfi = true_value.ufl_free_indices
         ffi = false_value.ufl_free_indices
-        ufl_assert(tfi == ffi, "Free index mismatch between conditional branches.")
+        if tfi != ffi:
+            error("Free index mismatch between conditional branches.")
         if isinstance(condition, (EQ, NE)):
-            ufl_assert(    condition.ufl_operands[0].ufl_shape == ()
-                       and condition.ufl_operands[0].ufl_free_indices == ()
-                       and condition.ufl_operands[1].ufl_shape == ()
-                       and condition.ufl_operands[1].ufl_free_indices == (),
-                       "Non-scalar == or != is not allowed.")
+            if not all((condition.ufl_operands[0].ufl_shape == (),
+                        condition.ufl_operands[0].ufl_free_indices == (),
+                        condition.ufl_operands[1].ufl_shape == (),
+                        condition.ufl_operands[1].ufl_free_indices == ())):
+                error("Non-scalar == or != is not allowed.")
 
         Operator.__init__(self, (condition, true_value, false_value))
 
@@ -237,11 +257,8 @@ class Conditional(Operator):
     def __str__(self):
         return "%s ? %s : %s" % tuple(parstr(o, self) for o in self.ufl_operands)
 
-    def __repr__(self):
-        return "Conditional(%r, %r, %r)" % self.ufl_operands
 
-
-#--- Specific functions higher level than a conditional ---
+# --- Specific functions higher level than a conditional ---
 
 @ufl_type(is_scalar=True, num_ops=1)
 class MinValue(Operator):
@@ -250,7 +267,8 @@ class MinValue(Operator):
 
     def __init__(self, left, right):
         Operator.__init__(self, (left, right))
-        ufl_assert(is_true_ufl_scalar(left) and is_true_ufl_scalar(right), "Expecting scalar arguments.")
+        if not (is_true_ufl_scalar(left) and is_true_ufl_scalar(right)):
+            error("Expecting scalar arguments.")
 
     def evaluate(self, x, mapping, component, index_values):
         a, b = self.ufl_operands
@@ -266,8 +284,6 @@ class MinValue(Operator):
     def __str__(self):
         return "min_value(%s, %s)" % self.ufl_operands
 
-    def __repr__(self):
-        return "MinValue(%r, %r)" % self.ufl_operands
 
 @ufl_type(is_scalar=True, num_ops=1)
 class MaxValue(Operator):
@@ -276,7 +292,8 @@ class MaxValue(Operator):
 
     def __init__(self, left, right):
         Operator.__init__(self, (left, right))
-        ufl_assert(is_true_ufl_scalar(left) and is_true_ufl_scalar(right), "Expecting scalar arguments.")
+        if not (is_true_ufl_scalar(left) and is_true_ufl_scalar(right)):
+            error("Expecting scalar arguments.")
 
     def evaluate(self, x, mapping, component, index_values):
         a, b = self.ufl_operands
@@ -291,6 +308,3 @@ class MaxValue(Operator):
 
     def __str__(self):
         return "max_value(%s, %s)" % self.ufl_operands
-
-    def __repr__(self):
-        return "MaxValue(%r, %r)" % self.ufl_operands
diff --git a/ufl/constantvalue.py b/ufl/constantvalue.py
index fa931bf..e2b0e0e 100644
--- a/ufl/constantvalue.py
+++ b/ufl/constantvalue.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines classes representing constant values."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,37 +19,41 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2011.
+# Modified by Massimiliano Leoni, 2016.
 
-from six.moves import zip
 from six.moves import xrange as range
 from six import iteritems
 
-from ufl.log import warning, error
-from ufl.assertions import ufl_assert, expecting_python_scalar
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error, UFLValueError
 from ufl.core.expr import Expr
 from ufl.core.terminal import Terminal
 from ufl.core.multiindex import Index, FixedIndex
-from ufl.utils.dicts import EmptyDict
 from ufl.core.ufl_type import ufl_type
 
-#--- Helper functions imported here for compatibility---
-from ufl.checks import is_python_scalar, is_ufl_scalar, is_true_ufl_scalar
+# --- Helper functions imported here for compatibility---
+from ufl.checks import is_python_scalar, is_ufl_scalar, is_true_ufl_scalar  # noqa: F401
+
 
 # Precision for float formatting
 precision = None
+
+
 def format_float(x):
     "Format float value based on global UFL precision."
     if precision is None:
-        return repr(x)
+        return "%s" % repr(x)
     else:
         return ("%%.%dg" % precision) % x
 
 
-#--- Base classes for constant types ---
+# --- Base classes for constant types ---
 
 @ufl_type(is_abstract=True)
 class ConstantValue(Terminal):
     __slots__ = ()
+
     def __init__(self):
         Terminal.__init__(self)
 
@@ -62,33 +66,35 @@ class ConstantValue(Terminal):
         return ()
 
 
-#--- Class for representing abstract constant symbol only for use internally in form compilers
-#@ufl_type()
-#class AbstractSymbol(ConstantValue):
-#    "UFL literal type: Representation of a constant valued symbol with unknown properties."
-#    __slots__ = ("_name", "ufl_shape")
-#    def __init__(self, name, shape):
-#        ConstantValue.__init__(self)
-#        self._name = name
-#        self.ufl_shape = shape
+# --- Class for representing abstract constant symbol only for use internally in form compilers
+# @ufl_type()
+# class AbstractSymbol(ConstantValue):
+#     "UFL literal type: Representation of a constant valued symbol with unknown properties."
+#     __slots__ = as_native_strings(("_name", "ufl_shape"))
+#     def __init__(self, name, shape):
+#         ConstantValue.__init__(self)
+#         self._name = name
+#         self.ufl_shape = shape
 #
-#    def __str__(self):
+#     def __str__(self):
 #        return "<Abstract symbol named '%s' with shape %s>" % (self._name, self.ufl_shape)
 #
-#    def __repr__(self):
-#        return "AbstractSymbol(%r, %r)" % (self._name, self.ufl_shape)
+#     def __repr__(self):
+#         r = "AbstractSymbol(%s, %s)" % (repr(self._name), repr(self.ufl_shape))
+#         return as_native_str(r)
 #
-#    def __eq__(self, other):
-#        return isinstance(other, AbstractSymbol) and self._name == other._name and self.ufl_shape == other.ufl_shape
+#     def __eq__(self, other):
+#         return isinstance(other, AbstractSymbol) and self._name == other._name and self.ufl_shape == other.ufl_shape
 
 
-#--- Class for representing zero tensors of different shapes ---
+# --- Class for representing zero tensors of different shapes ---
 
-# TODO: Add geometric dimension/domain and Argument dependencies to Zero?
+# TODO: Add geometric dimension/domain and Argument dependencies to
+# Zero?
 @ufl_type(is_literal=True)
 class Zero(ConstantValue):
     "UFL literal type: Representation of a zero valued expression."
-    __slots__ = ("ufl_shape", "ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings(("ufl_shape", "ufl_free_indices", "ufl_index_dimensions"))
 
     _cache = {}
 
@@ -122,21 +128,23 @@ class Zero(ConstantValue):
         if not free_indices:
             self.ufl_free_indices = ()
             self.ufl_index_dimensions = ()
-        elif all(isinstance(i, Index) for i in free_indices): # Handle old input format
-            if not (isinstance(index_dimensions, dict)
-                    and all(isinstance(i, Index) for i in index_dimensions.keys())):
+        elif all(isinstance(i, Index) for i in free_indices):  # Handle old input format
+            if not (isinstance(index_dimensions, dict) and
+                    all(isinstance(i, Index) for i in index_dimensions.keys())):
                 error("Expecting tuple of index dimensions, not %s" % str(index_dimensions))
             self.ufl_free_indices = tuple(sorted(i.count() for i in free_indices))
             self.ufl_index_dimensions = tuple(d for i, d in sorted(iteritems(index_dimensions), key=lambda x: x[0].count()))
-        else: # Handle new input format
+        else:  # Handle new input format
             if not all(isinstance(i, int) for i in free_indices):
                 error("Expecting tuple of integer free index ids, not %s" % str(free_indices))
-            if not (isinstance(index_dimensions, tuple)
-                    and all(isinstance(i, int) for i in index_dimensions)):
+            if not (isinstance(index_dimensions, tuple) and
+                    all(isinstance(i, int) for i in index_dimensions)):
                 error("Expecting tuple of integer index dimensions, not %s" % str(index_dimensions))
-            # TODO: Assume sorted and avoid this cost.
-            ufl_assert(sorted(free_indices) == list(free_indices),
-                       "Expecting sorted input. Remove this check later for efficiency.")
+
+            # Assuming sorted now to avoid this cost, enable for debuggin:
+            #if sorted(free_indices) != list(free_indices):
+            #    error("Expecting sorted input. Remove this check later for efficiency.")
+
             self.ufl_free_indices = free_indices
             self.ufl_index_dimensions = index_dimensions
 
@@ -146,11 +154,19 @@ class Zero(ConstantValue):
     def __str__(self):
         if self.ufl_shape == () and self.ufl_free_indices == ():
             return "0"
-        return "(0<%r, %r>)" % (self.ufl_shape, self.ufl_free_indices)
+        if self.ufl_free_indices == ():
+            return "0 (shape %s)" % (self.ufl_shape,)
+        if self.ufl_shape == ():
+            return "0 (index labels %s)" % (self.ufl_free_indices,)
+        return "0 (shape %s, index labels %s)" % (self.ufl_shape, self.ufl_free_indices)
 
     def __repr__(self):
-        return "Zero(%r, %r, %r)" % (self.ufl_shape,
-                self.ufl_free_indices, self.ufl_index_dimensions)
+        r = "Zero(%s, %s, %s)" % (
+            repr(self.ufl_shape),
+            repr(self.ufl_free_indices),
+            repr(self.ufl_index_dimensions),
+            )
+        return as_native_str(r)
 
     def __eq__(self, other):
         if isinstance(other, Zero):
@@ -180,6 +196,7 @@ class Zero(ConstantValue):
     def __int__(self):
         return 0
 
+
 def zero(*shape):
     "UFL literal constant: Return a zero tensor with the given shape."
     if len(shape) == 1 and isinstance(shape[0], tuple):
@@ -188,12 +205,12 @@ def zero(*shape):
         return Zero(shape)
 
 
-#--- Scalar value types ---
+# --- Scalar value types ---
 
 @ufl_type(is_abstract=True, is_scalar=True)
 class ScalarValue(ConstantValue):
     "A constant scalar value."
-    __slots__ = ("_value",)
+    __slots__ = as_native_strings(("_value",))
 
     def __init__(self, value):
         ConstantValue.__init__(self)
@@ -218,7 +235,8 @@ class ScalarValue(ConstantValue):
         if isinstance(other, self._ufl_class_):
             return self._value == other._value
         elif isinstance(other, (int, float)):
-            # FIXME: Disallow this, require explicit 'expr == IntValue(3)' instead to avoid ambiguities!
+            # FIXME: Disallow this, require explicit 'expr ==
+            # IntValue(3)' instead to avoid ambiguities!
             return other == self._value
         else:
             return False
@@ -257,7 +275,8 @@ class FloatValue(ScalarValue):
         ScalarValue.__init__(self, float(value))
 
     def __repr__(self):
-        return "%s(%s)" % (type(self).__name__, format_float(self._value))
+        r = "%s(%s)" % (type(self).__name__, format_float(self._value))
+        return as_native_str(r)
 
 
 @ufl_type(wraps_type=int, is_literal=True)
@@ -275,7 +294,8 @@ class IntValue(ScalarValue):
             # Always represent zero with Zero
             return Zero()
         elif abs(value) < 100:
-            # Small numbers are cached to reduce memory usage (fly-weight pattern)
+            # Small numbers are cached to reduce memory usage
+            # (fly-weight pattern)
             self = IntValue._cache.get(value)
             if self is not None:
                 return self
@@ -293,15 +313,16 @@ class IntValue(ScalarValue):
         pass
 
     def __repr__(self):
-        return "%s(%s)" % (type(self).__name__, repr(self._value))
+        r = "%s(%s)" % (type(self).__name__, repr(self._value))
+        return as_native_str(r)
 
 
-#--- Identity matrix ---
+# --- Identity matrix ---
 
 @ufl_type()
 class Identity(ConstantValue):
     "UFL literal type: Representation of an identity matrix."
-    __slots__ = ("_dim", "ufl_shape")
+    __slots__ = as_native_strings(("_dim", "ufl_shape"))
 
     def __init__(self, dim):
         ConstantValue.__init__(self)
@@ -309,11 +330,13 @@ class Identity(ConstantValue):
         self.ufl_shape = (dim, dim)
 
     def evaluate(self, x, mapping, component, index_values):
+        "Evaluates the identity matrix on the given components."
         a, b = component
         return 1 if a == b else 0
 
     def __getitem__(self, key):
-        ufl_assert(len(key) == 2, "Size mismatch for Identity.")
+        if len(key) != 2:
+            error("Size mismatch for Identity.")
         if all(isinstance(k, (int, FixedIndex)) for k in key):
             return IntValue(1) if (int(key[0]) == int(key[1])) else Zero()
         return Expr.__getitem__(self, key)
@@ -322,12 +345,14 @@ class Identity(ConstantValue):
         return "I"
 
     def __repr__(self):
-        return "Identity(%d)" % self._dim
+        r = "Identity(%d)" % self._dim
+        return as_native_str(r)
 
     def __eq__(self, other):
         return isinstance(other, Identity) and self._dim == other._dim
 
-#--- Permutation symbol ---
+
+# --- Permutation symbol ---
 
 @ufl_type()
 class PermutationSymbol(ConstantValue):
@@ -335,7 +360,7 @@ class PermutationSymbol(ConstantValue):
 
     This is also known as the Levi-Civita symbol, antisymmetric symbol,
     or alternating symbol."""
-    __slots__ = ("ufl_shape", "_dim")
+    __slots__ = as_native_strings(("ufl_shape", "_dim"))
 
     def __init__(self, dim):
         ConstantValue.__init__(self)
@@ -343,10 +368,12 @@ class PermutationSymbol(ConstantValue):
         self.ufl_shape = (dim,)*dim
 
     def evaluate(self, x, mapping, component, index_values):
+        "Evaluates the permutation symbol."
         return self.__eps(component)
 
     def __getitem__(self, key):
-        ufl_assert(len(key) == self._dim, "Size mismatch for PermutationSymbol.")
+        if len(key) != self._dim:
+            error("Size mismatch for PermutationSymbol.")
         if all(isinstance(k, (int, FixedIndex)) for k in key):
             return self.__eps(key)
         return Expr.__getitem__(self, key)
@@ -355,14 +382,17 @@ class PermutationSymbol(ConstantValue):
         return "eps"
 
     def __repr__(self):
-        return "PermutationSymbol(%d)" % self._dim
+        r = "PermutationSymbol(%d)" % self._dim
+        return as_native_str(r)
 
     def __eq__(self, other):
         return isinstance(other, PermutationSymbol) and self._dim == other._dim
 
     def __eps(self, x):
         """This function body is taken from
-        http://www.mathkb.com/Uwe/Forum.aspx/math/29865/N-integer-Levi-Civita"""
+        http://www.mathkb.com/Uwe/Forum.aspx/math/29865/N-integer-Levi-Civita
+
+        """
         result = IntValue(1)
         for i, x1 in enumerate(x):
             for j in range(i + 1, len(x)):
@@ -373,13 +403,15 @@ class PermutationSymbol(ConstantValue):
                     return Zero()
         return result
 
+
 def as_ufl(expression):
     "Converts expression to an Expr if possible."
     if isinstance(expression, Expr):
         return expression
-    if isinstance(expression, float):
+    elif isinstance(expression, float):
         return FloatValue(expression)
-    if isinstance(expression, int):
+    elif isinstance(expression, int):
         return IntValue(expression)
-    error(("Invalid type conversion: %s can not be converted to any UFL type.\n"+
-           "The representation of the object is:\n%r") % (type(expression), expression))
+    else:
+        raise UFLValueError("Invalid type conversion: %s can not be converted"
+                            " to any UFL type." % str(expression))
diff --git a/ufl/core/compute_expr_hash.py b/ufl/core/compute_expr_hash.py
index 7ff6af2..b061177 100644
--- a/ufl/core/compute_expr_hash.py
+++ b/ufl/core/compute_expr_hash.py
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
-"""Non-recursive traversal based hash computation algorithm.
+"""Non-recursive traversal-based hash computation algorithm.
 
-Fast iteration over nodes in an Expr DAG to compute
-memoized hashes for all unique nodes.
+Fast iteration over nodes in an ``Expr`` DAG to compute
+memorized hashes for all unique nodes.
 """
 
 # Copyright (C) 2015 Martin Sandve Alnæs
@@ -21,14 +21,15 @@ memoized hashes for all unique nodes.
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
+#
+# Modified by Massimiliano Leoni, 2016
 
 # This limits the _depth_ of expression trees
-_recursion_limit_ = 6400 # should be enough for everyone
+_recursion_limit_ = 6400  # should be enough for everyone
 
 
 def compute_expr_hash(expr):
-    """Compute hashes of expr and all its nodes efficiently without using Python recursion."""
+    """Compute hashes of *expr* and all its nodes efficiently, without using Python recursion."""
     if expr._hash is not None:
         return expr._hash
 
diff --git a/ufl/core/expr.py b/ufl/core/expr.py
index 0e28b72..a72fb78 100644
--- a/ufl/core/expr.py
+++ b/ufl/core/expr.py
@@ -1,15 +1,16 @@
 # -*- coding: utf-8 -*-
-"""This module defines the Expr class, the superclass
+"""This module defines the ``Expr`` class, the superclass
 for all expression tree node types in UFL.
 
 NB! A note about other operators not implemented here:
 
-More operators (special functions) on Exprs are defined in exproperators.py,
-as well as the transpose "A.T" and spatial derivative "a.dx(i)".
-This is to avoid circular dependencies between Expr and its subclasses.
+More operators (special functions) on ``Expr`` instances are defined in
+``exproperators.py``, as well as the transpose ``A.T`` and spatial derivative
+``a.dx(i)``.
+This is to avoid circular dependencies between ``Expr`` and its subclasses.
 """
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -27,29 +28,32 @@ This is to avoid circular dependencies between Expr and its subclasses.
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2008
+# Modified by Massimiliano Leoni, 2016
 
 from six.moves import xrange as range
 
-from ufl.log import warning, error, deprecate
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 
-#--- The base object for all UFL expression tree nodes ---
+
+# --- The base object for all UFL expression tree nodes ---
 
 class Expr(object):
     """Base class for all UFL expression types.
 
     *Instance properties*
-        Every expression instance will have certain properties.
-        Most important are the ``ufl_operands``, ``ufl_shape``,
+        Every ``Expr`` instance will have certain properties.
+        The most important ones are ``ufl_operands``, ``ufl_shape``,
         ``ufl_free_indices``, and ``ufl_index_dimensions`` properties.
         Expressions are immutable and hashable.
 
     *Type traits*
-        The Expr API defines a number of type traits that each subclass
+        The ``Expr`` API defines a number of type traits that each subclass
         needs to provide. Most of these are specified indirectly via
         the arguments to the ``ufl_type`` class decorator, allowing UFL
         to do some consistency checks and automate most of the traits
-        for most types. The type traits are accessed via a class or
-        instance object on the form obj._ufl_traitname_. See the source
+        for most types. Type traits are accessed via a class or
+        instance object of the form ``obj._ufl_traitname_``. See the source
         code for description of each type trait.
 
     *Operators*
@@ -67,7 +71,7 @@ class Expr(object):
         ``ufl_type`` to understand all the properties that may need to
         be specified is also a good idea. Note that many algorithms in
         UFL and form compilers will need handlers implemented for each
-        new type.
+        new type::.
 
         .. code-block:: python
 
@@ -91,13 +95,13 @@ class Expr(object):
         Giving a list of creation and deletion counts for each typecode.
     """
 
-    # --- Each Expr subclass must define __slots__ or _ufl_noslots_ at the top ---
-    # This is to freeze member variables for objects of this class and save memory
-    # by skipping the per-instance dict.
-
-    __slots__ = ("_hash",)
-    #_ufl_noslots_ = True
+    # --- Each Expr subclass must define __slots__ or _ufl_noslots_ at
+    # --- the top ---
+    # This is to freeze member variables for objects of this class and
+    # save memory by skipping the per-instance dict.
 
+    __slots__ = as_native_strings(("_hash",))
+    # _ufl_noslots_ = True
 
     # --- Basic object behaviour ---
 
@@ -116,37 +120,41 @@ class Expr(object):
     def __del__(self):
         pass
 
-    # This shows the principal behaviour of the hash function attached in ufl_type:
-    #def __hash__(self):
-    #    if self._hash is None:
-    #        self._hash = self._ufl_compute_hash_()
-    #    return self._hash
+    # This shows the principal behaviour of the hash function attached
+    # in ufl_type:
+    # def __hash__(self):
+    #     if self._hash is None:
+    #         self._hash = self._ufl_compute_hash_()
+    #     return self._hash
 
-    # --- Type traits are added to subclasses by the ufl_type class decorator ---
+    # --- Type traits are added to subclasses by the ufl_type class
+    # --- decorator ---
 
     # Note: Some of these are modified after the Expr class definition
-    # because Expr is not defined yet at this point.
-    # Note: Boolean type traits that categorize types are mostly set to
-    # None for Expr but should be True or False for any non-abstract type.
+    # because Expr is not defined yet at this point.  Note: Boolean
+    # type traits that categorize types are mostly set to None for
+    # Expr but should be True or False for any non-abstract type.
 
-    # A reference to the UFL class itself.
-    # This makes it possible to do type(f)._ufl_class_ and be sure you get
-    # the actual UFL class instead of a subclass from another library.
+    # A reference to the UFL class itself.  This makes it possible to
+    # do type(f)._ufl_class_ and be sure you get the actual UFL class
+    # instead of a subclass from another library.
     _ufl_class_ = None
 
-    # The handler name.
-    # This is the name of the handler function you implement for this type in a multifunction.
+    # The handler name.  This is the name of the handler function you
+    # implement for this type in a multifunction.
     _ufl_handler_name_ = "expr"
 
-    # The integer typecode, a contiguous index different for each type.
-    # This is used for fast lookup into e.g. multifunction handler tables.
+    # The integer typecode, a contiguous index different for each
+    # type.  This is used for fast lookup into e.g. multifunction
+    # handler tables.
     _ufl_typecode_ = 0
 
-    # Number of operands, "varying" for some types, or None if not applicable for abstract types.
+    # Number of operands, "varying" for some types, or None if not
+    # applicable for abstract types.
     _ufl_num_ops_ = None
 
-    # Type trait: If the type is abstract.
-    # An abstract class cannot be instantiated and does not need all properties specified.
+    # Type trait: If the type is abstract.  An abstract class cannot
+    # be instantiated and does not need all properties specified.
     _ufl_is_abstract_ = True
 
     # Type trait: If the type is terminal.
@@ -155,12 +163,13 @@ class Expr(object):
     # Type trait: If the type is a literal.
     _ufl_is_literal_ = None
 
-    # Type trait: If the type is classified as a 'terminal modifier', for form compiler use.
+    # Type trait: If the type is classified as a 'terminal modifier',
+    # for form compiler use.
     _ufl_is_terminal_modifier_ = None
 
-    # Type trait: If the type is a shaping operator.
-    # Shaping operations include indexing, slicing, transposing,
-    # i.e. not introducing computation of a new value.
+    # Type trait: If the type is a shaping operator.  Shaping
+    # operations include indexing, slicing, transposing, i.e. not
+    # introducing computation of a new value.
     _ufl_is_shaping_ = False
 
     # Type trait: If the type is in reference frame.
@@ -175,16 +184,17 @@ class Expr(object):
     # Type trait: If the type is a differential operator.
     _ufl_is_differential_ = None
 
-    # Type trait: If the type is purely scalar, having no shape or indices.
+    # Type trait: If the type is purely scalar, having no shape or
+    # indices.
     _ufl_is_scalar_ = None
 
     # Type trait: If the type never has free indices.
     _ufl_is_index_free_ = False
 
-
     # --- All subclasses must define these object attributes ---
 
-    # Each subclass of Expr is checked to have these properties in ufl_type
+    # Each subclass of Expr is checked to have these properties in
+    # ufl_type
     _ufl_required_properties_ = (
         # A tuple of operands, all of them Expr instances.
         "ufl_operands",
@@ -197,36 +207,39 @@ class Expr(object):
 
         # A tuple providing the int dimension for each free index.
         "ufl_index_dimensions",
-        )
+    )
 
-    # Each subclass of Expr is checked to have these methods in ufl_type
+    # Each subclass of Expr is checked to have these methods in
+    # ufl_type
     # FIXME: Add more and enable all
     _ufl_required_methods_ = (
         # To compute the hash on demand, this method is called.
         "_ufl_compute_hash_",
 
-        # The data returned from this method is used to compute the signature of a form
+        # The data returned from this method is used to compute the
+        # signature of a form
         "_ufl_signature_data_",
 
-        # The == operator must be implemented to compare for identical representation,
-        # used by set() and dict(). The __hash__ operator is added by ufl_type.
+        # The == operator must be implemented to compare for identical
+        # representation, used by set() and dict(). The __hash__
+        # operator is added by ufl_type.
         "__eq__",
 
-        # To reconstruct an object of the same type with operands or properties changed.
-        "_ufl_expr_reconstruct_", # Implemented in Operator and Terminal so this should never fail
+        # To reconstruct an object of the same type with operands or
+        # properties changed.
+        "_ufl_expr_reconstruct_",  # Implemented in Operator and Terminal so this should never fail
 
         "ufl_domains",
-        #"ufl_cell",
-        #"ufl_domain",
+        # "ufl_cell",
+        # "ufl_domain",
 
-        #"__str__",
-        #"__repr__",
+        # "__str__",
+        # "__repr__",
 
         # TODO: Add checks for methods/properties of terminals only?
         # Required for terminals:
-        #"is_cellwise_constant", # TODO: Rename to ufl_is_cellwise_constant?
-        )
-
+        # "is_cellwise_constant", # TODO: Rename to ufl_is_cellwise_constant?
+    )
 
     # --- Global variables for collecting all types ---
 
@@ -239,19 +252,21 @@ class Expr(object):
     # A global array of all Expr subclasses, indexed by typecode
     _ufl_all_classes_ = []
 
-    # A global dict mapping language_operator_name to the type it produces
+    # A global dict mapping language_operator_name to the type it
+    # produces
     _ufl_language_operators_ = {}
 
     # List of all terminal modifier types
     _ufl_terminal_modifiers_ = []
 
-
     # --- Mechanism for profiling object creation and deletion ---
 
-    # A global array of the number of initialized objects for each typecode
+    # A global array of the number of initialized objects for each
+    # typecode
     _ufl_obj_init_counts_ = [0]
 
-    # A global array of the number of deleted objects for each typecode
+    # A global array of the number of deleted objects for each
+    # typecode
     _ufl_obj_del_counts_ = [0]
 
     # Backup of default init and del
@@ -270,7 +285,7 @@ class Expr(object):
 
     @staticmethod
     def ufl_enable_profiling():
-        "Turn on object counting mechanism and reset counts to zero."
+        "Turn on the object counting mechanism and reset counts to zero."
         Expr.__init__ = Expr._ufl_profiling__init__
         Expr.__del__ = Expr._ufl_profiling__del__
         for i in range(len(Expr._ufl_obj_init_counts_)):
@@ -279,50 +294,47 @@ class Expr(object):
 
     @staticmethod
     def ufl_disable_profiling():
-        "Turn off object counting mechanism. Returns object init and del counts."
+        "Turn off the object counting mechanism. Return object init and del counts."
         Expr.__init__ = Expr._ufl_regular__init__
         Expr.__del__ = Expr._ufl_regular__del__
         return (Expr._ufl_obj_init_counts_, Expr._ufl_obj_del_counts_)
 
+    # === Abstract functions that must be implemented by subclasses ===
 
-    #=== Abstract functions that must be implemented by subclasses ===
-
-    #--- Functions for reconstructing expression ---
+    # --- Functions for reconstructing expression ---
 
     def _ufl_expr_reconstruct_(self, *operands):
         "Return a new object of the same type with new operands."
         raise NotImplementedError(self.__class__._ufl_expr_reconstruct_)
 
-    #--- Functions for geometric properties of expression ---
+    # --- Functions for geometric properties of expression ---
 
-    def ufl_domains(self): # TODO: Deprecate this and use extract_domains(expr)
+    def ufl_domains(self):  # TODO: Deprecate this and use extract_domains(expr)
         "Return all domains this expression is defined on."
         from ufl.domain import extract_domains
         return extract_domains(self)
 
-    def ufl_domain(self): # TODO: Deprecate this and use extract_unique_domain(expr)
-        "Return the single unique domain this expression is defined on or throw an error."
+    def ufl_domain(self):  # TODO: Deprecate this and use extract_unique_domain(expr)
+        "Return the single unique domain this expression is defined on, or throw an error."
         from ufl.domain import extract_unique_domain
         return extract_unique_domain(self)
 
-    def is_cellwise_constant(self): # TODO: Deprecate this and use is_cellwise_constant(expr)
-        "Return whether this expression is spatially constant over each cell."
-        from ufl.checks import is_cellwise_constant
-        deprecate("Expr.is_cellwise_constant() is deprecated, please use is_cellwise_constant(expr) instead.")
-        return is_cellwise_constant(self)
+    #def is_cellwise_constant(self):  # TODO: Deprecate this and use is_cellwise_constant(expr)
+    #    "Return whether this expression is spatially constant over each cell."
+    #    from ufl.checks import is_cellwise_constant
+    #    deprecate("Expr.is_cellwise_constant() is deprecated, please use is_cellwise_constant(expr) instead.")
+    #    return is_cellwise_constant(self)
 
-    #--- Functions for float evaluation ---
+    # --- Functions for float evaluation ---
 
     def evaluate(self, x, mapping, component, index_values):
         """Evaluate expression at given coordinate with given values for terminals."""
-        #from ufl.corealg.evaluate import evaluate_expr # TODO: Implement in corealg.eval module
-        #return evaluate_expr(self, ...) # ... then deprecate and remove expr.evaluate()
         error("Symbolic evaluation of %s not available." % self._ufl_class_.__name__)
 
     def _ufl_evaluate_scalar_(self):
         if self.ufl_shape or self.ufl_free_indices:
             raise TypeError("Cannot evaluate a nonscalar expression to a scalar value.")
-        return self(()) # No known x
+        return self(())  # No known x
 
     def __float__(self):
         "Try to evaluate as scalar and cast to float."
@@ -352,12 +364,12 @@ class Expr(object):
         ufl_from_type = "_ufl_from_{0}_".format(value.__class__.__name__)
         return getattr(Expr, ufl_from_type)(value)
 
-        #if hasattr(Expr, ufl_from_type):
-        #    return getattr(Expr, ufl_from_type)(value)
-        ## Fail gracefully if no valid type conversion found
-        #raise TypeError("Cannot convert a {0.__class__.__name__} to UFL type.".format(value))
+        # if hasattr(Expr, ufl_from_type):
+        #     return getattr(Expr, ufl_from_type)(value)
+        # Fail gracefully if no valid type conversion found
+        # raise TypeError("Cannot convert a {0.__class__.__name__} to UFL type.".format(value))
 
-    #--- Special functions for string representations ---
+    # --- Special functions for string representations ---
 
     # All subclasses must implement _ufl_signature_data_
     def _ufl_signature_data_(self, renumbering):
@@ -374,6 +386,14 @@ class Expr(object):
         "Return pretty print string representation of this object."
         raise NotImplementedError(self.__class__.__str__)
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
+    def _ufl_err_str_(self):
+        "Return a short string to represent this Expr in an error message."
+        return "<%s id=%d>" % (self._ufl_class_.__name__, id(self))
+
     def _repr_latex_(self):
         from ufl.algorithms import ufl2latex
         return "$%s$" % ufl2latex(self)
@@ -382,7 +402,7 @@ class Expr(object):
         from IPython.lib.latextools import latex_to_png
         return latex_to_png(self._repr_latex_())
 
-    #--- Special functions used for processing expressions ---
+    # --- Special functions used for processing expressions ---
 
     def __eq__(self, other):
         """Checks whether the two expressions are represented the
@@ -414,64 +434,79 @@ class Expr(object):
         "Round to nearest integer or to nearest nth decimal."
         return round(float(self), n)
 
+    # --- Deprecated functions
 
-    #--- Deprecated functions
-
-    def reconstruct(self, *operands):
-        "Return a new object of the same type with new operands."
-        deprecate("Expr.reconstruct() is deprecated, please use Expr._ufl_expr_reconstruct_() instead.")
-        return self._ufl_expr_reconstruct_(*operands)
+    #def reconstruct(self, *operands):
+    #    """Return a new object of the same type with new operands.
+    #    Deprecated, please use Expr._ufl_expr_reconstruct_() instead."""
+    #    deprecate("Expr.reconstruct() is deprecated, please use Expr._ufl_expr_reconstruct_() instead.")
+    #    return self._ufl_expr_reconstruct_(*operands)
 
     def geometric_dimension(self):
         "Return the geometric dimension this expression lives in."
         from ufl.domain import find_geometric_dimension
-        deprecate("Expr.geometric_dimension() is deprecated, please use find_geometric_dimension(expr) instead.")
         return find_geometric_dimension(self)
 
-    def domains(self):
-        deprecate("Expr.domains() is deprecated, please use .ufl_domains() instead.")
-        return self.ufl_domains()
-
-    def cell(self):
-        deprecate("Expr.cell() is deprecated, please use .ufl_domain() instead.")
-        domain = self.ufl_domain()
-        return domain.ufl_cell() if domain is not None else None
-
-    def domain(self):
-        deprecate("Expr.domain() is deprecated, please use .ufl_domain() instead.")
-        return self.ufl_domain()
-
-    def operands(self):
-        deprecate("Expr.operands() is deprecated, please use property Expr.ufl_operands instead.")
-        return self.ufl_operands
-
-    def shape(self):
-        "Return the tensor shape of the expression."
-        deprecate("Expr.shape() is deprecated, please use expr.ufl_shape instead.")
-        return self.ufl_shape
-
-    def rank(self):
-        "Return the tensor rank of the expression."
-        deprecate("Expr.rank() is deprecated," +
-                  " please use len(expr.ufl_shape) instead.")
-        return len(self.ufl_shape)
-
-    def free_indices(self):
-        from ufl.core.multiindex import Index
-        deprecate("Expr.free_indices() is deprecated," +
-                  " please use property Expr.ufl_free_indices instead.")
-        return tuple(Index(count=i) for i in self.ufl_free_indices)
-
-    def index_dimensions(self):
-        from ufl.core.multiindex import Index
-        from ufl.utils.dicts import EmptyDict
-        deprecate("Expr.index_dimensions() is deprecated," +
-                  " please use property Expr.ufl_index_dimensions instead.")
-        idims = { Index(count=i): d for i, d in zip(self.ufl_free_indices, self.ufl_index_dimensions) }
-        return idims or EmptyDict
-
-
-# Initializing traits here because Expr is not defined in the class declaration
+    #def domains(self):
+    #    "Deprecated, please use .ufl_domains() instead."
+    #    deprecate("Expr.domains() is deprecated, please use .ufl_domains() instead.")
+    #    return self.ufl_domains()
+
+    #def cell(self):
+    #    "Deprecated, please use .ufl_domain().ufl_cell() instead."
+    #    deprecate("Expr.cell() is deprecated, please use .ufl_domain() instead.")
+    #    domain = self.ufl_domain()
+    #    return domain.ufl_cell() if domain is not None else None
+
+    #def domain(self):
+    #    "Deprecated, please use .ufl_domain() instead."
+    #    deprecate("Expr.domain() is deprecated, please use .ufl_domain() instead.")
+    #    return self.ufl_domain()
+
+    #def operands(self):
+    #    "Deprecated, please use Expr.ufl_operands instead."
+    #    deprecate("Expr.operands() is deprecated, please use property Expr.ufl_operands instead.")
+    #    return self.ufl_operands
+
+    #def shape(self):
+    #    """Return the tensor shape of the expression.
+    #    Deprecated, please use Expr.ufl_shape instead."""
+    #    deprecate("Expr.shape() is deprecated, please use Expr.ufl_shape instead.")
+    #    return self.ufl_shape
+
+    #def rank(self):
+    #    """Return the tensor rank of the expression.
+    #    Deprecated, please use len(expr.ufl_shape) instead."""
+    #    deprecate("Expr.rank() is deprecated," +
+    #              " please use len(expr.ufl_shape) instead.")
+    #    return len(self.ufl_shape)
+
+    #def free_indices(self):
+    #    "Deprecated, please use property Expr.ufl_free_indices instead."
+    #    from ufl.core.multiindex import Index
+    #    deprecate("Expr.free_indices() is deprecated," +
+    #              " please use property Expr.ufl_free_indices instead.")
+    #    return tuple(Index(count=i) for i in self.ufl_free_indices)
+
+    #def index_dimensions(self):
+    #    "Deprecated, please use property Expr.ufl_index_dimensions instead."
+    #    from ufl.core.multiindex import Index
+    #    from ufl.utils.dicts import EmptyDict
+    #    deprecate("Expr.index_dimensions() is deprecated," +
+    #              " please use property Expr.ufl_index_dimensions instead.")
+    #    idims = {Index(count=i): d for i, d in zip(self.ufl_free_indices, self.ufl_index_dimensions)}
+    #    return idims or EmptyDict
+
+
+# Initializing traits here because Expr is not defined in the class
+# declaration
 Expr._ufl_class_ = Expr
 Expr._ufl_all_handler_names_.add(Expr)
 Expr._ufl_all_classes_.append(Expr)
+
+
+def ufl_err_str(expr):
+    if hasattr(expr, "_ufl_err_str_"):
+        return expr._ufl_err_str_()
+    else:
+        return repr(expr)
diff --git a/ufl/core/multiindex.py b/ufl/core/multiindex.py
index 62860d9..8c8c422 100644
--- a/ufl/core/multiindex.py
+++ b/ufl/core/multiindex.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module defines the single index types and some internal index utilities."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -17,29 +17,39 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016.
 
+#import six
 from six.moves import xrange as range
 
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.utils.counted import counted_init
 from ufl.core.ufl_type import ufl_type
 from ufl.core.terminal import Terminal
 
-
 # Export list for ufl.classes
-__all_classes__ = ["IndexBase", "FixedIndex", "Index"]
+__all_classes__ = as_native_strings(["IndexBase", "FixedIndex", "Index"])
 
 
 class IndexBase(object):
+    """Base class for all indices."""
     __slots__ = ()
+
     def __init__(self):
         pass
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
 
+# @six.python_2_unicode_compatible
 class FixedIndex(IndexBase):
     """UFL value: An index with a specific value assigned."""
-    __slots__ = ("_value", "_hash")
+    __slots__ = as_native_strings(("_value", "_hash"))
 
     _cache = {}
 
@@ -77,14 +87,16 @@ class FixedIndex(IndexBase):
         return "%d" % self._value
 
     def __repr__(self):
-        return "FixedIndex(%d)" % self._value
+        r = "FixedIndex(%d)" % self._value
+        return as_native_str(r)
 
 
+# @six.python_2_unicode_compatible
 class Index(IndexBase):
     """UFL value: An index with no value assigned.
 
     Used to represent free indices in Einstein indexing notation."""
-    __slots__ = ("_count",)
+    __slots__ = as_native_strings(("_count",))
 
     _globalcount = 0
 
@@ -108,13 +120,14 @@ class Index(IndexBase):
         return "i_%s" % c
 
     def __repr__(self):
-        return "Index(%d)" % self._count
+        r = "Index(%d)" % self._count
+        return as_native_str(r)
 
 
 @ufl_type()
 class MultiIndex(Terminal):
     "Represents a sequence of indices, either fixed or free."
-    __slots__ = ("_indices",)
+    __slots__ = as_native_strings(("_indices",))
 
     _cache = {}
 
@@ -122,7 +135,8 @@ class MultiIndex(Terminal):
         return (self._indices,)
 
     def __new__(cls, indices):
-        ufl_assert(isinstance(indices, tuple), "Expecting a tuple of indices.")
+        if not isinstance(indices, tuple):
+            error("Expecting a tuple of indices.")
 
         if all(isinstance(ind, FixedIndex) for ind in indices):
             # Cache multiindices consisting of purely fixed indices (aka flyweight pattern)
@@ -134,7 +148,8 @@ class MultiIndex(Terminal):
             MultiIndex._cache[key] = self
         else:
             # Create a new object if we have any free indices (too many combinations to cache)
-            ufl_assert(all(isinstance(ind, IndexBase) for ind in indices), "Expecting only Index and FixedIndex objects.")
+            if not all(isinstance(ind, IndexBase) for ind in indices):
+                error("Expecting only Index and FixedIndex objects.")
             self = Terminal.__new__(cls)
 
         # Initialize here instead of in __init__ to avoid overwriting self._indices from cached objects
@@ -149,6 +164,7 @@ class MultiIndex(Terminal):
         self._indices = indices
 
     def indices(self):
+        "Return tuple of indices."
         return self._indices
 
     def _ufl_compute_hash_(self):
@@ -159,6 +175,7 @@ class MultiIndex(Terminal):
             self._indices == other._indices
 
     def evaluate(self, x, mapping, component, index_values):
+        "Evaluate index."
         # Build component from index values
         component = []
         for i in self._indices:
@@ -170,17 +187,21 @@ class MultiIndex(Terminal):
 
     @property
     def ufl_shape(self):
+        "This shall not be used."
         error("Multiindex has no shape (it is not a tensor expression).")
 
     @property
     def ufl_free_indices(self):
+        "This shall not be used."
         error("Multiindex has no free indices (it is not a tensor expression).")
 
     @property
     def ufl_index_dimensions(self):
+        "This shall not be used."
         error("Multiindex has no free indices (it is not a tensor expression).")
 
     def is_cellwise_constant(self):
+        "Always True."
         return True
 
     def ufl_domains(self):
@@ -209,7 +230,8 @@ class MultiIndex(Terminal):
         return ", ".join(str(i) for i in self._indices)
 
     def __repr__(self):
-        return "MultiIndex(%r)" % (self._indices,)
+        r = "MultiIndex(%s)" % repr(self._indices)
+        return as_native_str(r)
 
     # --- Iteration protocol ---
 
@@ -224,6 +246,7 @@ class MultiIndex(Terminal):
 
 
 def as_multi_index(ii, shape=None):
+    "Return a ``MultiIndex`` version of *ii*."
     if isinstance(ii, MultiIndex):
         return ii
     elif not isinstance(ii, tuple):
@@ -232,5 +255,5 @@ def as_multi_index(ii, shape=None):
 
 
 def indices(n):
-    "UFL value: Return a tuple of n new Index objects."
+    "UFL value: Return a tuple of :math:`n` new Index objects."
     return tuple(Index() for i in range(n))
diff --git a/ufl/core/operator.py b/ufl/core/operator.py
index 92ec39c..f6aef18 100644
--- a/ufl/core/operator.py
+++ b/ufl/core/operator.py
@@ -1,7 +1,6 @@
 # -*- coding: utf-8 -*-
-"Base class for all operators, i.e. non-terminal expr types."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,26 +18,28 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2008
+# Modified by Massimiliano Leoni, 2016
 
-from six import iteritems
-
-from ufl.log import error
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 from ufl.core.expr import Expr
 from ufl.core.ufl_type import ufl_type
 
 
-#--- Base class for operator objects ---
+# --- Base class for operator objects ---
 
 @ufl_type(is_abstract=True, is_terminal=False)
 class Operator(Expr):
-    __slots__ = ("ufl_operands",)
+    "Base class for all operators, i.e. non-terminal expression types."
+    __slots__ = as_native_strings(("ufl_operands",))
 
     def __init__(self, operands=None):
         Expr.__init__(self)
 
-        # If operands is None, the type sets this itself. This is to get around
-        # some tricky too-fancy __new__/__init__ design in algebra.py, for now.
-        # It would be nicer to make the classes in algebra.py pass operands here.
+        # If operands is None, the type sets this itself. This is to
+        # get around some tricky too-fancy __new__/__init__ design in
+        # algebra.py, for now.  It would be nicer to make the classes
+        # in algebra.py pass operands here.
         if operands is not None:
             self.ufl_operands = operands
 
@@ -52,3 +53,10 @@ class Operator(Expr):
     def _ufl_compute_hash_(self):
         "Compute a hash code for this expression. Used by sets and dicts."
         return hash((self._ufl_typecode_,) + tuple(hash(o) for o in self.ufl_operands))
+
+    def __repr__(self):
+        "Default repr string construction for operators."
+        # This should work for most cases
+        r = "%s(%s)" % (self._ufl_class_.__name__,
+            ", ".join(repr(op) for op in self.ufl_operands))
+        return as_native_str(r)
diff --git a/ufl/core/terminal.py b/ufl/core/terminal.py
index 6a55e2c..52c3d38 100644
--- a/ufl/core/terminal.py
+++ b/ufl/core/terminal.py
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
-"""This module defines the Terminal class, the superclass
-for all types that are terminal nodes in the expression trees."""
+"""This module defines the ``Terminal`` class, the superclass
+for all types that are terminal nodes in an expression tree."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,13 +20,14 @@ for all types that are terminal nodes in the expression trees."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2008
+# Modified by Massimiliano Leoni, 2016
 
 from ufl.log import error, warning
-from ufl.assertions import ufl_assert
 from ufl.core.expr import Expr
 from ufl.core.ufl_type import ufl_type
 
-#--- Base class for terminal objects ---
+
+# --- Base class for terminal objects ---
 
 @ufl_type(is_abstract=True, is_terminal=True)
 class Terminal(Expr):
@@ -51,7 +52,7 @@ class Terminal(Expr):
         raise NotImplementedError("Missing implementation of domains().")
 
     def evaluate(self, x, mapping, component, index_values, derivatives=()):
-        "Get self from mapping and return the component asked for."
+        "Get *self* from *mapping* and return the component asked for."
         f = mapping.get(self)
         # No mapping, trying to evaluate self as a constant
         if f is None:
@@ -100,10 +101,12 @@ class Terminal(Expr):
         return repr(self) == repr(other)
 
 
-#--- Subgroups of terminals ---
+# --- Subgroups of terminals ---
 
 @ufl_type(is_abstract=True)
 class FormArgument(Terminal):
+    "An abstract class for a form argument."
     __slots__ = ()
+
     def __init__(self):
         Terminal.__init__(self)
diff --git a/ufl/core/ufl_id.py b/ufl/core/ufl_id.py
index 8bb7b3b..e52e3b6 100644
--- a/ufl/core/ufl_id.py
+++ b/ufl/core/ufl_id.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Utilites for types with a globally counted unique id attached to each object."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -17,25 +17,38 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
+
+from ufl.utils.py23 import as_native_str
+
 
 def attach_ufl_id(cls):
-    """Equip class with .ufl_id() and handle bookkeeping.
+    """Equip class with ``.ufl_id()`` and handle bookkeeping.
 
     Usage:
 
-        # 1) Apply to class
-        @attach_ufl_id
-        class MyClass(object):
-            # 2) If __slots__ is defined, include "_ufl_id" attribute
+        1. Apply to class::
+
+            @attach_ufl_id
+            class MyClass(object):
+
+        2. If ``__slots__`` is defined, include ``_ufl_id`` attribute::
+
             __slots__ = ("_ufl_id",)
-            # 3) Add keyword argument to constructor
+
+        3. Add keyword argument to constructor::
+
             def __init__(self, *args, ufl_id=None):
-                # 4) Call self._init_ufl_id with ufl_id and assign to ._ufl_id attribute
-                self._ufl_id = self._init_ufl_id(ufl_id)
+
+        4. Call ``self._init_ufl_id`` with ``ufl_id`` and assign to ``._ufl_id``
+           attribute::
+
+            self._ufl_id = self._init_ufl_id(ufl_id)
 
     Result:
 
-        MyClass().ufl_id() returns unique value for each constructed object.
+        ``MyClass().ufl_id()`` returns unique value for each constructed object.
 
     """
 
@@ -55,7 +68,7 @@ def attach_ufl_id(cls):
 
     # Modify class:
     if hasattr(cls, "__slots__"):
-        assert "_ufl_id" in cls.__slots__
+        assert as_native_str("_ufl_id") in cls.__slots__
     cls._ufl_global_id = 0
     cls.ufl_id = _get_ufl_id
     cls._init_ufl_id = _init_ufl_id(cls)
diff --git a/ufl/core/ufl_type.py b/ufl/core/ufl_type.py
index b39919a..b95618f 100644
--- a/ufl/core/ufl_type.py
+++ b/ufl/core/ufl_type.py
@@ -1,19 +1,37 @@
 # -*- coding: utf-8 -*-
 
-
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
+#
+# This file is part of UFL.
+#
+# UFL is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# UFL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
+
+import six
 from ufl.core.expr import Expr
 from ufl.core.compute_expr_hash import compute_expr_hash
-
 from ufl.utils.formatting import camel2underscore
-from ufl.utils.dicts import EmptyDict
+
 
 # Make UFL type coercion available under the as_ufl name
-#as_ufl = Expr._ufl_coerce_
+# as_ufl = Expr._ufl_coerce_
 
 def attach_operators_from_hash_data(cls):
-    """Class decorator to attach __hash__, __eq__ and __ne__ implementations.
+    """Class decorator to attach ``__hash__``, ``__eq__`` and ``__ne__`` implementations.
 
-    These are implemented in terms of a ._ufl_hash_data() method on the class,
+    These are implemented in terms of a ``._ufl_hash_data()`` method on the class,
     which should return a tuple or hashable and comparable data.
     """
     assert hasattr(cls, "_ufl_hash_data_")
@@ -35,8 +53,9 @@ def attach_operators_from_hash_data(cls):
 
     return cls
 
+
 def get_base_attr(cls, name):
-    "Return first non-None attribute of given name among base classes."
+    "Return first non-``None`` attribute of given name among base classes."
     for base in cls.mro():
         if hasattr(base, name):
             attr = getattr(base, name)
@@ -44,20 +63,23 @@ def get_base_attr(cls, name):
                 return attr
     return None
 
+
 def set_trait(cls, basename, value, inherit=False):
-    """Assign a trait to class with namespacing _ufl_basename_ applied.
+    """Assign a trait to class with namespacing ``_ufl_basename_`` applied.
 
-    If trait value is None, optionally inherit it from the closest base class that has it.
+    If trait value is ``None``, optionally inherit it from the closest base class that has it.
     """
     name = "_ufl_" + basename + "_"
     if value is None and inherit:
         value = get_base_attr(cls, name)
     setattr(cls, name, value)
 
+
 def determine_num_ops(cls, num_ops, unop, binop, rbinop):
-    # Try to determine num_ops from other traits or baseclass,
-    # or require num_ops to be set for non-abstract classes
-    # if it cannot be determined automatically
+    "Determine number of operands for this type."
+    # Try to determine num_ops from other traits or baseclass, or
+    # require num_ops to be set for non-abstract classes if it cannot
+    # be determined automatically
     if num_ops is not None:
         return num_ops
     elif cls._ufl_is_terminal_:
@@ -70,21 +92,23 @@ def determine_num_ops(cls, num_ops, unop, binop, rbinop):
         # Determine from base class
         return get_base_attr(cls, "_ufl_num_ops_")
 
+
 def check_is_terminal_consistency(cls):
-    "Check for consistency in is_terminal trait among superclasses."
+    "Check for consistency in ``is_terminal`` trait among superclasses."
     if cls._ufl_is_terminal_ is None:
-        msg = ("Class {0.__name__} has not specified the is_terminal trait."
-            + " Did you forget to inherit from Terminal or Operator?")
+        msg = ("Class {0.__name__} has not specified the is_terminal trait." +
+               " Did you forget to inherit from Terminal or Operator?")
         raise TypeError(msg.format(cls))
 
     base_is_terminal = get_base_attr(cls, "_ufl_is_terminal_")
     if base_is_terminal is not None and cls._ufl_is_terminal_ != base_is_terminal:
-        msg = ("Conflicting given and automatic 'is_terminal' trait for class {0.__name__}."
-            + " Check if you meant to inherit from Terminal or Operator.")
+        msg = ("Conflicting given and automatic 'is_terminal' trait for class {0.__name__}." +
+               " Check if you meant to inherit from Terminal or Operator.")
         raise TypeError(msg.format(cls))
 
+
 def check_abstract_trait_consistency(cls):
-    "Check that the first base classes up to Expr are other UFL types."
+    "Check that the first base classes up to ``Expr`` are other UFL types."
     for base in cls.mro():
         if base is Expr:
             break
@@ -93,8 +117,10 @@ def check_abstract_trait_consistency(cls):
                    "is not an abstract subclass of {2.__name__}.")
             raise TypeError(msg.format(base, cls, Expr))
 
+
 def check_has_slots(cls):
-    "Check if type has __slots__ unless it is marked as exception with _ufl_noslots_"
+    """Check if type has ``__slots__`` unless it is marked as exception with
+    ``_ufl_noslots_``."""
     if "_ufl_noslots_" in cls.__dict__:
         return
 
@@ -110,6 +136,7 @@ def check_has_slots(cls):
                    "{1.__name__} with __slots__ missing.")
             raise TypeError(msg.format(cls, base))
 
+
 def check_type_traits_consistency(cls):
     "Execute a variety of consistency checks on the ufl type traits."
 
@@ -142,6 +169,7 @@ def check_type_traits_consistency(cls):
             msg = "Non-scalar class {0.__name__} is has a scalar base class."
             raise TypeError(msg.format(cls))
 
+
 def check_implements_required_methods(cls):
     """Check if type implements the required methods."""
     if not cls._ufl_is_abstract_:
@@ -153,6 +181,7 @@ def check_implements_required_methods(cls):
                 msg = "Required method {1} of class {0.__name__} is not callable."
                 raise TypeError(msg.format(cls, attr))
 
+
 def check_implements_required_properties(cls):
     "Check if type implements the required properties."
     if not cls._ufl_is_abstract_:
@@ -164,10 +193,12 @@ def check_implements_required_properties(cls):
                 msg = "Required property {1} of class {0.__name__} is a callable method."
                 raise TypeError(msg.format(cls, attr))
 
-def attach_implementations_of_indexing_interface(cls, inherit_shape_from_operand,
+
+def attach_implementations_of_indexing_interface(cls,
+                                                 inherit_shape_from_operand,
                                                  inherit_indices_from_operand):
-    # Scalar or index-free? Then we can simplify the implementation of tensor
-    # properties by attaching them here.
+    # Scalar or index-free? Then we can simplify the implementation of
+    # tensor properties by attaching them here.
     if cls._ufl_is_scalar_:
         cls.ufl_shape = ()
 
@@ -175,8 +206,9 @@ def attach_implementations_of_indexing_interface(cls, inherit_shape_from_operand
         cls.ufl_free_indices = ()
         cls.ufl_index_dimensions = ()
 
-    # Automate direct inheriting of shape and indices from one of the operands.
-    # This simplifies refactoring because a lot of types do this.
+    # Automate direct inheriting of shape and indices from one of the
+    # operands.  This simplifies refactoring because a lot of types do
+    # this.
     if inherit_shape_from_operand is not None:
         def _inherited_ufl_shape(self):
             return self.ufl_operands[inherit_shape_from_operand].ufl_shape
@@ -185,30 +217,35 @@ def attach_implementations_of_indexing_interface(cls, inherit_shape_from_operand
     if inherit_indices_from_operand is not None:
         def _inherited_ufl_free_indices(self):
             return self.ufl_operands[inherit_indices_from_operand].ufl_free_indices
+
         def _inherited_ufl_index_dimensions(self):
             return self.ufl_operands[inherit_indices_from_operand].ufl_index_dimensions
         cls.ufl_free_indices = property(_inherited_ufl_free_indices)
         cls.ufl_index_dimensions = property(_inherited_ufl_index_dimensions)
 
+
 def update_global_expr_attributes(cls):
-    "Update global Expr attributes, mainly by adding cls to global collections of ufl types."
+    "Update global ``Expr`` attributes, mainly by adding *cls* to global collections of ufl types."
     Expr._ufl_all_classes_.append(cls)
     Expr._ufl_all_handler_names_.add(cls._ufl_handler_name_)
 
     if cls._ufl_is_terminal_modifier_:
         Expr._ufl_terminal_modifiers_.append(cls)
 
-    # Add to collection of language operators.
-    # This collection is used later to populate the official language namespace.
-    # TODO: I don't think this functionality is fully completed, check it out later.
+    # Add to collection of language operators.  This collection is
+    # used later to populate the official language namespace.
+    # TODO: I don't think this functionality is fully completed, check
+    # it out later.
     if not cls._ufl_is_abstract_ and hasattr(cls, "_ufl_function_"):
         cls._ufl_function_.__func__.__doc__ = cls.__doc__
         Expr._ufl_language_operators_[cls._ufl_handler_name_] = cls._ufl_function_
 
-    # Append space for counting object creation and destriction of this this type.
+    # Append space for counting object creation and destriction of
+    # this this type.
     Expr._ufl_obj_init_counts_.append(0)
     Expr._ufl_obj_del_counts_.append(0)
 
+
 def ufl_type(is_abstract=False,
              is_terminal=None,
              is_scalar=False,
@@ -227,9 +264,8 @@ def ufl_type(is_abstract=False,
              wraps_type=None,
              unop=None,
              binop=None,
-             rbinop=None
-             ):
-    """This decorator is to be applied to every subclass in the UFL Expr hierarchy.
+             rbinop=None):
+    """This decorator is to be applied to every subclass in the UFL ``Expr`` hierarchy.
 
     This decorator contains a number of checks that are
     intended to enforce uniform behaviour across UFL types.
@@ -261,9 +297,11 @@ def ufl_type(is_abstract=False,
 
         set_trait(cls, "is_terminal", is_terminal, inherit=True)
         set_trait(cls, "is_literal", is_literal, inherit=True)
-        set_trait(cls, "is_terminal_modifier", is_terminal_modifier, inherit=True)
+        set_trait(cls, "is_terminal_modifier", is_terminal_modifier,
+                  inherit=True)
         set_trait(cls, "is_shaping", is_shaping, inherit=True)
-        set_trait(cls, "is_in_reference_frame", is_in_reference_frame, inherit=True)
+        set_trait(cls, "is_in_reference_frame", is_in_reference_frame,
+                  inherit=True)
         set_trait(cls, "is_restriction", is_restriction, inherit=True)
         set_trait(cls, "is_evaluation", is_evaluation, inherit=True)
         set_trait(cls, "is_differential", is_differential, inherit=True)
@@ -314,17 +352,24 @@ def ufl_type(is_abstract=False,
             setattr(Expr, rbinop, _ufl_expr_rbinop_)
         """
 
-        # Make sure every non-abstract class has its own __hash__ and __eq__.
-        # Python 3 will set __hash__ to None if cls has __eq__, but we've
-        # implemented it in a separate function and want to inherit/use that
-        # for all types. Allow overriding by setting use_default_hash=False.
+        # Make sure every non-abstract class has its own __hash__ and
+        # __eq__.  Python 3 will set __hash__ to None if cls has
+        # __eq__, but we've implemented it in a separate function and
+        # want to inherit/use that for all types. Allow overriding by
+        # setting use_default_hash=False.
         if use_default_hash:
             cls.__hash__ = compute_expr_hash
 
-        # NB! This function conditionally adds some methods to the class!
-        # This approach significantly reduces the amount of small functions to
-        # implement across all the types but of course it's a bit more opaque.
-        attach_implementations_of_indexing_interface(cls, inherit_shape_from_operand,
+        # FIXME: Apply this if everything beomes unicode
+        if 0:
+            cls = six.python_2_unicode_compatible(cls)
+
+        # NB! This function conditionally adds some methods to the
+        # class!  This approach significantly reduces the amount of
+        # small functions to implement across all the types but of
+        # course it's a bit more opaque.
+        attach_implementations_of_indexing_interface(cls,
+                                                     inherit_shape_from_operand,
                                                      inherit_indices_from_operand)
 
         # Update Expr
diff --git a/ufl/corealg/map_dag.py b/ufl/corealg/map_dag.py
index 0931c77..3d2f325 100644
--- a/ufl/corealg/map_dag.py
+++ b/ufl/corealg/map_dag.py
@@ -17,6 +17,8 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
 from ufl.core.expr import Expr
 from ufl.corealg.traversal import unique_post_traversal, cutoff_unique_post_traversal
@@ -24,26 +26,26 @@ from ufl.corealg.multifunction import MultiFunction
 
 
 def map_expr_dag(function, expression, compress=True):
-    """Apply a function to each subexpression node in expression dag.
+    """Apply a function to each subexpression node in an expression DAG.
 
-    If compress is True (default), the output object from
-    the function is cached in a dict and reused such that the
-    resulting expression dag does not contain duplicate objects.
+    If *compress* is ``True`` (default) the output object from
+    the function is cached in a ``dict`` and reused such that the
+    resulting expression DAG does not contain duplicate objects.
 
-    Returns the result of the final function call.
+    Return the result of the final function call.
     """
     result, = map_expr_dags(function, [expression], compress=compress)
     return result
 
 
 def map_expr_dags(function, expressions, compress=True):
-    """Apply a function to each subexpression node in expression dag.
+    """Apply a function to each subexpression node in an expression DAG.
 
-    If compress is True (default), the output object from
-    the function is cached in a dict and reused such that the
-    resulting expression dag does not contain duplicate objects.
+    If *compress* is ``True`` (default) the output object from
+    the function is cached in a ``dict`` and reused such that the
+    resulting expression DAG does not contain duplicate objects.
 
-    Returns a list with the result of the final function call for each expression.
+    Return a list with the result of the final function call for each expression.
     """
 
     # Temporary data structures
diff --git a/ufl/corealg/multifunction.py b/ufl/corealg/multifunction.py
index 3f34557..8fa615a 100644
--- a/ufl/corealg/multifunction.py
+++ b/ufl/corealg/multifunction.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
-"""Base class for multifunctions with UFL Expr type dispatch."""
+"""Base class for multifunctions with UFL ``Expr`` type dispatch."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -17,18 +17,23 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
 from inspect import getargspec
 
 from ufl.log import error
 from ufl.core.expr import Expr
 
+
 def get_num_args(function):
+    "Return the number of arguments accepted by *function*."
     insp = getargspec(function)
     return len(insp[0]) + int(insp[1] is not None)
 
+
 def memoized_handler(handler):
-    "Function decorator to memoize MultiFunction handlers."
+    "Function decorator to memoize ``MultiFunction`` handlers."
     def _memoized_handler(self, o):
         c = getattr(self, "_memoized_handler_cache")
         r = c.get(o)
@@ -38,16 +43,18 @@ def memoized_handler(handler):
         return r
     return _memoized_handler
 
+
 class MultiFunction(object):
-    """Base class for collections of nonrecursive expression node handlers.
+    """Base class for collections of non-recursive expression node handlers.
 
-    Subclass this (remember to call the __init__ method of this class),
-    and implement handler functions for each Expr type, using the lower case
-    handler name of the type (exprtype._ufl_handler_name_).
+    Subclass this (remember to call the ``__init__`` method of this class),
+    and implement handler functions for each ``Expr`` type, using the lower case
+    handler name of the type (``exprtype._ufl_handler_name_``).
 
-    This class is optimized for efficient type based dispatch in the __call__
+    This class is optimized for efficient type based dispatch in the
+    ``__call__``
     operator via typecode based lookup of the handler function bound to the
-    algorithm object. Of course function call overhead of Python still applies.
+    algorithm object. Of course Python's function call overhead still applies.
     """
 
     _handlers_cache = {}
@@ -59,25 +66,30 @@ class MultiFunction(object):
         algorithm_class = type(self)
         cache_data = MultiFunction._handlers_cache.get(algorithm_class)
         if not cache_data:
-            cache_data = [None]*len(Expr._ufl_all_classes_)
+            handler_names = [None]*len(Expr._ufl_all_classes_)
 
-            # Iterate over the inheritance chain for each Expr subclass
-            # (NB! This assumes that all UFL classes inherits from
-            # a single Expr subclass and that the first superclass
-            # is always from the UFL Expr hierarchy!)
+            # Iterate over the inheritance chain for each Expr
+            # subclass (NB! This assumes that all UFL classes inherits
+            # from a single Expr subclass and that the first
+            # superclass is always from the UFL Expr hierarchy!)
             for classobject in Expr._ufl_all_classes_:
                 for c in classobject.mro():
-                    # Register classobject with handler for the first encountered superclass
-                    name = c._ufl_handler_name_
-                    if hasattr(self, name):
-                        cache_data[classobject._ufl_typecode_] = name
+                    # Register classobject with handler for the first
+                    # encountered superclass
+                    handler_name = c._ufl_handler_name_
+                    if hasattr(self, handler_name):
+                        handler_names[classobject._ufl_typecode_] = handler_name
                         break
+            is_cutoff_type = [get_num_args(getattr(self, name)) == 2
+                              for name in handler_names]
+            cache_data = (handler_names, is_cutoff_type)
             MultiFunction._handlers_cache[algorithm_class] = cache_data
 
-        # Build handler list for this particular class
-        # (get functions bound to self, these cannot be cached)
-        self._handlers = [getattr(self, name) for name in cache_data]
-        self._is_cutoff_type = [get_num_args(h) == 2 for h in self._handlers]
+        # Build handler list for this particular class (get functions
+        # bound to self, these cannot be cached)
+        handler_names, is_cutoff_type = cache_data
+        self._handlers = [getattr(self, name) for name in handler_names]
+        self._is_cutoff_type = is_cutoff_type
 
         # Create cache for memoized_handler
         self._memoized_handler_cache = {}
@@ -94,6 +106,7 @@ class MultiFunction(object):
         """Reuse object if operands are the same objects.
 
         Use in your own subclass by setting e.g.
+        ::
 
             expr = MultiFunction.reuse_if_untouched
 
diff --git a/ufl/corealg/traversal.py b/ufl/corealg/traversal.py
index fd74d10..17fb771 100644
--- a/ufl/corealg/traversal.py
+++ b/ufl/corealg/traversal.py
@@ -2,7 +2,7 @@
 """Various expression traversal utilities.
 
 The algorithms here are non-recursive, which is faster than recursion
-by a factor 10 or so because of the function call overhead.
+by a factor of 10 or so because of the function call overhead.
 """
 
 # Copyright (C) 2008-2016 Martin Sandve Alnæs
@@ -21,14 +21,15 @@ by a factor 10 or so because of the function call overhead.
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
+#
+# Modified by Massimiliano Leoni, 2016
 
 # This limits the _depth_ of expression trees
-_recursion_limit_ = 6400 # should be enough for everyone
+_recursion_limit_ = 6400  # should be enough for everyone
 
 
 def pre_traversal(expr):
-    """Yields o for each tree node o in expr, parent before child."""
+    """Yield ``o`` for each tree node ``o`` in *expr*, parent before child."""
     stack = [None]*_recursion_limit_
     stack[0] = expr
     stacksize = 1
@@ -42,7 +43,7 @@ def pre_traversal(expr):
 
 
 def post_traversal(expr):
-    """Yields o for each node o in expr, child before parent."""
+    """Yield ``o`` for each node ``o`` in *expr*, child before parent."""
     stack = [None]*_recursion_limit_
     stacksize = 0
 
@@ -64,7 +65,8 @@ def post_traversal(expr):
 
 
 def cutoff_post_traversal(expr, cutofftypes):
-    """Yields o for each node o in expr, child before parent, but skipping subtrees of the cutofftypes."""
+    """Yield ``o`` for each node ``o`` in *expr*, child before parent, but
+    skipping subtrees of the cutofftypes."""
     stack = [None]*_recursion_limit_
     stacksize = 0
 
@@ -90,9 +92,9 @@ def cutoff_post_traversal(expr, cutofftypes):
 
 
 def unique_pre_traversal(expr, visited=None):
-    """Yields o for each tree node o in expr, parent before child.
+    """Yield ``o`` for each tree node ``o`` in *expr*, parent before child.
 
-    This version only visits each node once!
+    This version only visits each node once.
     """
     stack = [None]*_recursion_limit_
     stack[0] = expr
@@ -111,9 +113,9 @@ def unique_pre_traversal(expr, visited=None):
 
 
 def unique_post_traversal(expr, visited=None):
-    """Yields o for each node o in expr, child before parent.
+    """Yield ``o`` for each node ``o`` in *expr*, child before parent.
 
-    Never visits a node twice."""
+    Never visit a node twice."""
     stack = [None]*_recursion_limit_
     stack[0] = (expr, list(expr.ufl_operands))
     stacksize = 1
@@ -134,9 +136,9 @@ def unique_post_traversal(expr, visited=None):
 
 
 def cutoff_unique_post_traversal(expr, cutofftypes, visited=None):
-    """Yields o for each node o in expr, child before parent.
+    """Yield ``o`` for each node ``o`` in *expr*, child before parent.
 
-    Never visits a node twice."""
+    Never visit a node twice."""
     stack = [None]*_recursion_limit_
     stack[0] = (expr, () if cutofftypes[expr._ufl_typecode_] else list(expr.ufl_operands))
     stacksize = 1
@@ -157,7 +159,7 @@ def cutoff_unique_post_traversal(expr, cutofftypes, visited=None):
 
 
 def traverse_terminals(expr):
-    "Iterate over all terminal objects in expression, including duplicates."
+    "Iterate over all terminal objects in *expr*, including duplicates."
     stack = [None]*_recursion_limit_
     stack[0] = expr
     stacksize = 1
@@ -173,7 +175,7 @@ def traverse_terminals(expr):
 
 
 def traverse_unique_terminals(expr, visited=None):
-    "Iterate over all terminal objects in expression, not including duplicates."
+    "Iterate over all terminal objects in *expr*, not including duplicates."
     stack = [None]*_recursion_limit_
     stack[0] = expr
     stacksize = 1
diff --git a/ufl/differentiation.py b/ufl/differentiation.py
index 07387d5..0488af6 100644
--- a/ufl/differentiation.py
+++ b/ufl/differentiation.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Differential operators."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,78 +20,88 @@
 #
 # Modified by Anders Logg, 2009.
 
-from ufl.log import warning, error
-from ufl.assertions import ufl_assert
-from ufl.utils.dicts import subdict, mergedicts, EmptyDict
-
+from ufl.log import error
+from ufl.utils.py23 import as_native_strings
 from ufl.core.expr import Expr
 from ufl.core.terminal import Terminal
 from ufl.core.operator import Operator
 from ufl.core.ufl_type import ufl_type
-from ufl.core.multiindex import Index, FixedIndex, MultiIndex
 
 from ufl.exprcontainers import ExprList, ExprMapping
 from ufl.constantvalue import Zero
 from ufl.coefficient import Coefficient
-from ufl.indexed import Indexed
 from ufl.variable import Variable
 from ufl.precedence import parstr
 from ufl.domain import find_geometric_dimension
 from ufl.checks import is_cellwise_constant
 
-#--- Basic differentiation objects ---
+
+# --- Basic differentiation objects ---
 
 @ufl_type(is_abstract=True,
           is_differential=True)
 class Derivative(Operator):
     "Base class for all derivative types."
     __slots__ = ()
+
     def __init__(self, operands):
         Operator.__init__(self, operands)
 
- at ufl_type(num_ops=4, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
+
+ at ufl_type(num_ops=4, inherit_shape_from_operand=0,
+          inherit_indices_from_operand=0)
 class CoefficientDerivative(Derivative):
     """Derivative of the integrand of a form w.r.t. the
     degrees of freedom in a discrete Coefficient."""
     __slots__ = ()
 
-    def __new__(cls, integrand, coefficients, arguments, coefficient_derivatives):
-        ufl_assert(isinstance(coefficients, ExprList),
-                   "Expecting ExprList instance with Coefficients.")
-        ufl_assert(isinstance(arguments, ExprList),
-                   "Expecting ExprList instance with Arguments.")
-        ufl_assert(isinstance(coefficient_derivatives, ExprMapping),
-                   "Expecting ExprMapping for coefficient derivatives.")
+    def __new__(cls, integrand, coefficients, arguments,
+                coefficient_derivatives):
+        if not isinstance(coefficients, ExprList):
+            error("Expecting ExprList instance with Coefficients.")
+        if not isinstance(arguments, ExprList):
+            error("Expecting ExprList instance with Arguments.")
+        if not isinstance(coefficient_derivatives, ExprMapping):
+            error("Expecting ExprMapping for coefficient derivatives.")
         if isinstance(integrand, Zero):
             return integrand
         return Derivative.__new__(cls)
 
-    def __init__(self, integrand, coefficients, arguments, coefficient_derivatives):
+    def __init__(self, integrand, coefficients, arguments,
+                 coefficient_derivatives):
         if not isinstance(coefficient_derivatives, ExprMapping):
             coefficient_derivatives = ExprMapping(coefficient_derivatives)
-        Derivative.__init__(self, (integrand, coefficients, arguments, coefficient_derivatives))
+        Derivative.__init__(self, (integrand, coefficients, arguments,
+                                   coefficient_derivatives))
 
     def __str__(self):
         return "d/dfj { %s }, with fh=%s, dfh/dfj = %s, and coefficient derivatives %s"\
-            % (self.ufl_operands[0], self.ufl_operands[1], self.ufl_operands[2], self.ufl_operands[3])
+            % (self.ufl_operands[0], self.ufl_operands[1],
+               self.ufl_operands[2], self.ufl_operands[3])
 
-    def __repr__(self):
-        return "CoefficientDerivative(%r, %r, %r, %r)"\
-            % (self.ufl_operands[0], self.ufl_operands[1], self.ufl_operands[2], self.ufl_operands[3])
 
 @ufl_type(num_ops=2)
 class VariableDerivative(Derivative):
-    __slots__ = ("ufl_shape", "ufl_free_indices", "ufl_index_dimensions",)
+    __slots__ = as_native_strings((
+        "ufl_shape",
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+    ))
+
     def __new__(cls, f, v):
         # Checks
-        ufl_assert(isinstance(f, Expr), "Expecting an Expr in VariableDerivative.")
-        ufl_assert(isinstance(v, (Variable, Coefficient)), "Expecting a Variable in VariableDerivative.")
-        ufl_assert(not v.ufl_free_indices, "Differentiation variable cannot have free indices.")
+        if not isinstance(f, Expr):
+            error("Expecting an Expr in VariableDerivative.")
+        if not isinstance(v, (Variable, Coefficient)):
+            error("Expecting a Variable in VariableDerivative.")
+        if v.ufl_free_indices:
+            error("Differentiation variable cannot have free indices.")
 
         # Simplification
         # Return zero if expression is trivially independent of variable
         if f._ufl_is_terminal_ and f != v:
-            return Zero(f.ufl_shape + v.ufl_shape, f.ufl_free_indices, f.ufl_index_dimensions)
+            return Zero(f.ufl_shape + v.ufl_shape, f.ufl_free_indices,
+                        f.ufl_index_dimensions)
 
         # Construction
         return Derivative.__new__(cls)
@@ -105,30 +115,31 @@ class VariableDerivative(Derivative):
     def __str__(self):
         if isinstance(self.ufl_operands[0], Terminal):
             return "d%s/d[%s]" % (self.ufl_operands[0], self.ufl_operands[1])
-        return "d/d[%s] %s" % (self.ufl_operands[1], parstr(self.ufl_operands[0], self))
+        return "d/d[%s] %s" % (self.ufl_operands[1],
+                               parstr(self.ufl_operands[0], self))
 
-    def __repr__(self):
-        return "VariableDerivative(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
-#--- Compound differentiation objects ---
+# --- Compound differentiation objects ---
 
 @ufl_type(is_abstract=True)
 class CompoundDerivative(Derivative):
     "Base class for all compound derivative types."
     __slots__ = ()
+
     def __init__(self, operands):
         Derivative.__init__(self, operands)
 
 
 @ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True)
 class Grad(CompoundDerivative):
-    __slots__ = ("_dim",)
+    __slots__ = as_native_strings(("_dim",))
 
     def __new__(cls, f):
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
             dim = find_geometric_dimension(f)
-            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices, f.ufl_index_dimensions)
+            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices,
+                        f.ufl_index_dimensions)
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -138,20 +149,21 @@ class Grad(CompoundDerivative):
     def _ufl_expr_reconstruct_(self, op):
         "Return a new object of the same type with new operands."
         if is_cellwise_constant(op):
-            ufl_assert(op.ufl_shape == self.ufl_operands[0].ufl_shape,
-                       "Operand shape mismatch in Grad reconstruct.")
-            ufl_assert(self.ufl_operands[0].ufl_free_indices == op.ufl_free_indices,
-                       "Free index mismatch in Grad reconstruct.")
-            return Zero(self.ufl_shape, self.ufl_free_indices, self.ufl_index_dimensions)
+            if op.ufl_shape != self.ufl_operands[0].ufl_shape:
+                error("Operand shape mismatch in Grad reconstruct.")
+            if self.ufl_operands[0].ufl_free_indices != op.ufl_free_indices:
+                error("Free index mismatch in Grad reconstruct.")
+            return Zero(self.ufl_shape, self.ufl_free_indices,
+                        self.ufl_index_dimensions)
         return self._ufl_class_(op)
 
     def evaluate(self, x, mapping, component, index_values, derivatives=()):
         "Get child from mapping and return the component asked for."
-        r = len(component)
         component, i = component[:-1], component[-1]
         derivatives = derivatives + (i,)
-        result = self.ufl_operands[0].evaluate(x, mapping, component, index_values,
-                                  derivatives=derivatives)
+        result = self.ufl_operands[0].evaluate(x, mapping, component,
+                                               index_values,
+                                               derivatives=derivatives)
         return result
 
     @property
@@ -161,21 +173,18 @@ class Grad(CompoundDerivative):
     def __str__(self):
         return "grad(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Grad(%r)" % self.ufl_operands[0]
 
- at ufl_type(num_ops=1,
-          inherit_indices_from_operand=0,
-          is_terminal_modifier=True,
+ at ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True,
           is_in_reference_frame=True)
 class ReferenceGrad(CompoundDerivative):
-    __slots__ = ("_dim",)
+    __slots__ = as_native_strings(("_dim",))
 
     def __new__(cls, f):
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
             dim = f.ufl_domain().topological_dimension()
-            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices, f.ufl_index_dimensions)
+            return Zero(f.ufl_shape + (dim,), f.ufl_free_indices,
+                        f.ufl_index_dimensions)
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -185,20 +194,21 @@ class ReferenceGrad(CompoundDerivative):
     def _ufl_expr_reconstruct_(self, op):
         "Return a new object of the same type with new operands."
         if is_cellwise_constant(op):
-            ufl_assert(op.ufl_shape == self.ufl_operands[0].ufl_shape,
-                       "Operand shape mismatch in ReferenceGrad reconstruct.")
-            ufl_assert(self.ufl_operands[0].ufl_free_indices == op.ufl_free_indices,
-                       "Free index mismatch in ReferenceGrad reconstruct.")
-            return Zero(self.ufl_shape, self.ufl_free_indices, self.ufl_index_dimensions)
+            if op.ufl_shape != self.ufl_operands[0].ufl_shape:
+                error("Operand shape mismatch in ReferenceGrad reconstruct.")
+            if self.ufl_operands[0].ufl_free_indices != op.ufl_free_indices:
+                error("Free index mismatch in ReferenceGrad reconstruct.")
+            return Zero(self.ufl_shape, self.ufl_free_indices,
+                        self.ufl_index_dimensions)
         return self._ufl_class_(op)
 
     def evaluate(self, x, mapping, component, index_values, derivatives=()):
         "Get child from mapping and return the component asked for."
-        r = len(component)
         component, i = component[:-1], component[-1]
         derivatives = derivatives + (i,)
-        result = self.ufl_operands[0].evaluate(x, mapping, component, index_values,
-                                  derivatives=derivatives)
+        result = self.ufl_operands[0].evaluate(x, mapping, component,
+                                               index_values,
+                                               derivatives=derivatives)
         return result
 
     @property
@@ -208,20 +218,18 @@ class ReferenceGrad(CompoundDerivative):
     def __str__(self):
         return "reference_grad(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "ReferenceGrad(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True)
 class Div(CompoundDerivative):
     __slots__ = ()
 
     def __new__(cls, f):
-        ufl_assert(not f.ufl_free_indices,
-            "Free indices in the divergence argument is not allowed.")
+        if f.ufl_free_indices:
+            error("Free indices in the divergence argument is not allowed.")
 
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
-            return Zero(f.ufl_shape[:-1]) # No free indices asserted above
+            return Zero(f.ufl_shape[:-1])  # No free indices asserted above
 
         return CompoundDerivative.__new__(cls)
 
@@ -235,23 +243,19 @@ class Div(CompoundDerivative):
     def __str__(self):
         return "div(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Div(%r)" % self.ufl_operands[0]
 
- at ufl_type(num_ops=1,
-          inherit_indices_from_operand=0,
-          is_terminal_modifier=True,
+ at ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True,
           is_in_reference_frame=True)
 class ReferenceDiv(CompoundDerivative):
     __slots__ = ()
 
     def __new__(cls, f):
-        ufl_assert(not f.ufl_free_indices,
-            "Free indices in the divergence argument is not allowed.")
+        if f.ufl_free_indices:
+            error("Free indices in the divergence argument is not allowed.")
 
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
-            return Zero(f.ufl_shape[:-1]) # No free indices asserted above
+            return Zero(f.ufl_shape[:-1])  # No free indices asserted above
 
         return CompoundDerivative.__new__(cls)
 
@@ -265,18 +269,17 @@ class ReferenceDiv(CompoundDerivative):
     def __str__(self):
         return "reference_div(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "ReferenceDiv(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=1, inherit_indices_from_operand=0)
 class NablaGrad(CompoundDerivative):
-    __slots__ = ("_dim",)
+    __slots__ = as_native_strings(("_dim",))
 
     def __new__(cls, f):
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
             dim = find_geometric_dimension(f)
-            return Zero((dim,) + f.ufl_shape, f.ufl_free_indices, f.ufl_index_dimensions)
+            return Zero((dim,) + f.ufl_shape, f.ufl_free_indices,
+                        f.ufl_index_dimensions)
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -286,10 +289,10 @@ class NablaGrad(CompoundDerivative):
     def _ufl_expr_reconstruct_(self, op):
         "Return a new object of the same type with new operands."
         if is_cellwise_constant(op):
-            ufl_assert(op.ufl_shape == self.ufl_operands[0].ufl_shape,
-                       "Operand shape mismatch in NablaGrad reconstruct.")
-            ufl_assert(self.ufl_operands[0].ufl_free_indices == op.ufl_free_indices,
-                       "Free index mismatch in NablaGrad reconstruct.")
+            if op.ufl_shape != self.ufl_operands[0].ufl_shape:
+                error("Operand shape mismatch in NablaGrad reconstruct.")
+            if self.ufl_operands[0].ufl_free_indices != op.ufl_free_indices:
+                error("Free index mismatch in NablaGrad reconstruct.")
             return Zero(self.ufl_shape, self.ufl_free_indices,
                         self.ufl_index_dimensions)
         return self._ufl_class_(op)
@@ -301,20 +304,18 @@ class NablaGrad(CompoundDerivative):
     def __str__(self):
         return "nabla_grad(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "NablaGrad(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=1, inherit_indices_from_operand=0)
 class NablaDiv(CompoundDerivative):
     __slots__ = ()
 
     def __new__(cls, f):
-        ufl_assert(not f.ufl_free_indices,
-            "Free indices in the divergence argument is not allowed.")
+        if f.ufl_free_indices:
+            error("Free indices in the divergence argument is not allowed.")
 
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
-            return Zero(f.ufl_shape[1:]) # No free indices asserted above
+            return Zero(f.ufl_shape[1:])  # No free indices asserted above
 
         return CompoundDerivative.__new__(cls)
 
@@ -328,25 +329,26 @@ class NablaDiv(CompoundDerivative):
     def __str__(self):
         return "nabla_div(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "NablaDiv(%r)" % self.ufl_operands[0]
 
-_curl_shapes = { (): (2,), (2,): (), (3,): (3,) }
+_curl_shapes = {(): (2,), (2,): (), (3,): (3,)}
+
+
 @ufl_type(num_ops=1, inherit_indices_from_operand=0, is_terminal_modifier=True)
 class Curl(CompoundDerivative):
-    __slots__ = ("ufl_shape",)
+    __slots__ = as_native_strings(("ufl_shape",))
 
     def __new__(cls, f):
         # Validate input
         sh = f.ufl_shape
-        ufl_assert(f.ufl_shape in ((), (2,), (3,)), "Expecting a scalar, 2D vector or 3D vector.")
-        ufl_assert(not f.ufl_free_indices,
-            "Free indices in the curl argument is not allowed.")
+        if f.ufl_shape not in ((), (2,), (3,)):
+            error("Expecting a scalar, 2D vector or 3D vector.")
+        if f.ufl_free_indices:
+            error("Free indices in the curl argument is not allowed.")
 
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
-            sh = { (): (2,), (2,): (), (3,): (3,) }[sh]
-            return Zero(sh) # No free indices asserted above
+            sh = {(): (2,), (2,): (), (3,): (3,)}[sh]
+            return Zero(sh)  # No free indices asserted above
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -357,27 +359,24 @@ class Curl(CompoundDerivative):
     def __str__(self):
         return "curl(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Curl(%r)" % self.ufl_operands[0]
 
- at ufl_type(num_ops=1,
-          inherit_indices_from_operand=0,
-          is_terminal_modifier=True,
-          is_in_reference_frame=True)
+ at ufl_type(num_ops=1, inherit_indices_from_operand=0,
+          is_terminal_modifier=True, is_in_reference_frame=True)
 class ReferenceCurl(CompoundDerivative):
-    __slots__ = ("ufl_shape",)
+    __slots__ = as_native_strings(("ufl_shape",))
 
     def __new__(cls, f):
         # Validate input
         sh = f.ufl_shape
-        ufl_assert(f.ufl_shape in ((), (2,), (3,)), "Expecting a scalar, 2D vector or 3D vector.")
-        ufl_assert(not f.ufl_free_indices,
-            "Free indices in the curl argument is not allowed.")
+        if f.ufl_shape not in ((), (2,), (3,)):
+            error("Expecting a scalar, 2D vector or 3D vector.")
+        if f.ufl_free_indices:
+            error("Free indices in the curl argument is not allowed.")
 
         # Return zero if expression is trivially constant
         if is_cellwise_constant(f):
-            sh = { (): (2,), (2,): (), (3,): (3,) }[sh]
-            return Zero(sh) # No free indices asserted above
+            sh = {(): (2,), (2,): (), (3,): (3,)}[sh]
+            return Zero(sh)  # No free indices asserted above
         return CompoundDerivative.__new__(cls)
 
     def __init__(self, f):
@@ -387,6 +386,3 @@ class ReferenceCurl(CompoundDerivative):
 
     def __str__(self):
         return "reference_curl(%s)" % self.ufl_operands[0]
-
-    def __repr__(self):
-        return "ReferenceCurl(%r)" % self.ufl_operands[0]
diff --git a/ufl/domain.py b/ufl/domain.py
index 2012570..d2bf651 100644
--- a/ufl/domain.py
+++ b/ufl/domain.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Types for representing a geometric domain."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -22,35 +22,33 @@
 # Modified by Kristian B. Oelgaard, 2009
 # Modified by Marie E. Rognes 2012
 
-from collections import defaultdict
-from six import iteritems
+# import six
+import numbers
 
-from ufl.core.terminal import Terminal
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 from ufl.core.ufl_type import attach_operators_from_hash_data
 from ufl.core.ufl_id import attach_ufl_id
 from ufl.corealg.traversal import traverse_unique_terminals
-from ufl.log import warning, error, deprecate
-from ufl.assertions import ufl_assert
-from ufl.utils.formatting import istr
-from ufl.utils.dicts import EmptyDict
-from ufl.protocols import id_or_none
-from ufl.cell import as_cell, AbstractCell, Cell, TensorProductCell
+from ufl.log import error
+from ufl.cell import as_cell, AbstractCell, TensorProductCell
+from ufl.finiteelement.tensorproductelement import TensorProductElement
 
 
 # Export list for ufl.classes
-__all_classes__ = ["AbstractDomain", "Mesh", "MeshView", "TensorProductMesh"]
+__all_classes__ = as_native_strings(["AbstractDomain", "Mesh", "MeshView", "TensorProductMesh"])
 
 
 class AbstractDomain(object):
     """Symbolic representation of a geometric domain with only a geometric and topological dimension."""
     def __init__(self, topological_dimension, geometric_dimension):
         # Validate dimensions
-        ufl_assert(isinstance(geometric_dimension, int),
-                   "Expecting integer geometric dimension, not '%r'" % (geometric_dimension,))
-        ufl_assert(isinstance(topological_dimension, int),
-                   "Expecting integer topological dimension, not '%r'" % (topological_dimension,))
-        ufl_assert(topological_dimension <= geometric_dimension,
-                   "Topological dimension cannot be larger than geometric dimension.")
+        if not isinstance(geometric_dimension, numbers.Integral):
+            error("Expecting integer geometric dimension, not %s" % (geometric_dimension.__class__,))
+        if not isinstance(topological_dimension, numbers.Integral):
+            error("Expecting integer topological dimension, not %s" % (topological_dimension.__class__,))
+        if topological_dimension > geometric_dimension:
+            error("Topological dimension cannot be larger than geometric dimension.")
 
         # Store validated dimensions
         self._topological_dimension = topological_dimension
@@ -64,13 +62,19 @@ class AbstractDomain(object):
         "Return the dimension of the topology of this domain."
         return self._topological_dimension
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
 
-# TODO: Would it be useful to have a domain representing R^d? E.g. for Expression.
-#class EuclideanSpace(AbstractDomain):
-#    def __init__(self, geometric_dimension):
-#        AbstractDomain.__init__(self, geometric_dimension, geometric_dimension)
 
+# TODO: Would it be useful to have a domain representing R^d? E.g. for
+# Expression.
+# class EuclideanSpace(AbstractDomain):
+#     def __init__(self, geometric_dimension):
+#         AbstractDomain.__init__(self, geometric_dimension, geometric_dimension)
 
+
+# @six.python_2_unicode_compatible
 @attach_operators_from_hash_data
 @attach_ufl_id
 class Mesh(AbstractDomain):
@@ -92,7 +96,8 @@ class Mesh(AbstractDomain):
         if isinstance(coordinate_element, AbstractCell):
             from ufl.finiteelement import VectorElement
             cell = coordinate_element
-            coordinate_element = VectorElement("Lagrange", cell, 1, dim=cell.geometric_dimension())
+            coordinate_element = VectorElement("Lagrange", cell, 1,
+                                               dim=cell.geometric_dimension())
 
         # Store coordinate element
         self._ufl_coordinate_element = coordinate_element
@@ -116,10 +121,11 @@ class Mesh(AbstractDomain):
         return (self._ufl_coordinate_element.degree() == 1) and self.ufl_cell().is_simplex()
 
     def __repr__(self):
-        return "Mesh(%r, %r)" % (self._ufl_coordinate_element, self._ufl_id)
+        r = "Mesh(%s, %s)" % (repr(self._ufl_coordinate_element), repr(self._ufl_id))
+        return as_native_str(r)
 
     def __str__(self):
-        return "<Mesh #%s with coordinates parameterized by %s>" % (self._ufl_id, self._ufl_coordinate_element)
+        return "<Mesh #%s>" % (self._ufl_id,)
 
     def _ufl_hash_data_(self):
         return (self._ufl_id, self._ufl_coordinate_element)
@@ -127,27 +133,30 @@ class Mesh(AbstractDomain):
     def _ufl_signature_data_(self, renumbering):
         return ("Mesh", renumbering[self], self._ufl_coordinate_element)
 
-    # NB! Dropped __lt__ here, don't want users to write 'mesh1 < mesh2'.
+    # NB! Dropped __lt__ here, don't want users to write 'mesh1 <
+    # mesh2'.
     def _ufl_sort_key_(self):
         typespecific = (self._ufl_id, self._ufl_coordinate_element)
-        return (self.geometric_dimension(), self.topological_dimension(), "Mesh", typespecific)
+        return (self.geometric_dimension(), self.topological_dimension(),
+                "Mesh", typespecific)
 
     # Deprecations inherited from Domain
-    def cell(self):
-        deprecate("Mesh.cell() is deprecated, please use .ufl_cell() instead.")
-        return self.ufl_cell()
+    #def cell(self):
+    #    deprecate("Mesh.cell() is deprecated, please use .ufl_cell() instead.")
+    #    return self.ufl_cell()
 
-    def coordinates(self):
-        error("Coordinate function support has been removed!\n"
-              "Use mesh.ufl_coordinate_element() to get the coordinate element,\n"
-              "and SpatialCoordinate(mesh) to represent the coordinate field in a form.")
+    #def coordinates(self):
+    #    error("Coordinate function support has been removed!\n"
+    #          "Use mesh.ufl_coordinate_element() to get the coordinate element,\n"
+    #          "and SpatialCoordinate(mesh) to represent the coordinate field in a form.")
 
-    def ufl_coordinates(self):
-        error("Coordinate function support has been removed!\n"
-              "Use mesh.ufl_coordinate_element() to get the coordinate element,\n"
-              "and SpatialCoordinate(mesh) to represent the coordinate field in a form.")
+    #def ufl_coordinates(self):
+    #    error("Coordinate function support has been removed!\n"
+    #          "Use mesh.ufl_coordinate_element() to get the coordinate element,\n"
+    #          "and SpatialCoordinate(mesh) to represent the coordinate field in a form.")
 
 
+# @six.python_2_unicode_compatible
 @attach_operators_from_hash_data
 @attach_ufl_id
 class MeshView(AbstractDomain):
@@ -159,6 +168,7 @@ class MeshView(AbstractDomain):
         self._ufl_mesh = mesh
 
         # Derive dimensions from element
+        coordinate_element = mesh.ufl_coordinate_element()
         gdim, = coordinate_element.value_shape()
         tdim = coordinate_element.cell().topological_dimension()
         AbstractDomain.__init__(self, tdim, gdim)
@@ -173,23 +183,30 @@ class MeshView(AbstractDomain):
         return self._ufl_mesh.is_piecewise_linear_simplex_domain()
 
     def __repr__(self):
-        return "MeshView(%r, %r, %r)" % (self._ufl_mesh, self.topological_dimension(), self._ufl_id)
+        tdim = self.topological_dimension()
+        r = "MeshView(%s, %s, %s)" % (repr(self._ufl_mesh), repr(tdim), repr(self._ufl_id))
+        return as_native_str(r)
 
     def __str__(self):
-        return "<MeshView #%s of dimension %d over mesh %s>" % (self._ufl_id, self.topological_dimension(), self._ufl_mesh)
+        return "<MeshView #%s of dimension %d over mesh %s>" % (
+            self._ufl_id, self.topological_dimension(), self._ufl_mesh)
 
     def _ufl_hash_data_(self):
         return (self._ufl_id,) + self._ufl_mesh._ufl_hash_data_()
 
     def _ufl_signature_data_(self, renumbering):
-        return ("MeshView", renumbering[self], self._ufl_mesh._ufl_signature_data_(renumbering))
+        return ("MeshView", renumbering[self],
+                self._ufl_mesh._ufl_signature_data_(renumbering))
 
-    # NB! Dropped __lt__ here, don't want users to write 'mesh1 < mesh2'.
+    # NB! Dropped __lt__ here, don't want users to write 'mesh1 <
+    # mesh2'.
     def _ufl_sort_key_(self):
         typespecific = (self._ufl_id, self._ufl_mesh)
-        return (self.geometric_dimension(), self.topological_dimension(), "MeshView", typespecific)
+        return (self.geometric_dimension(), self.topological_dimension(),
+                "MeshView", typespecific)
 
 
+# @six.python_2_unicode_compatible
 @attach_operators_from_hash_data
 @attach_ufl_id
 class TensorProductMesh(AbstractDomain):
@@ -202,7 +219,7 @@ class TensorProductMesh(AbstractDomain):
 
         # TODO: Is this what we want to do?
         # Build cell from mesh cells
-        self._ufl_cell = TensorProductCell([mesh.ufl_cell() for mesh in meshes])
+        self._ufl_cell = TensorProductCell(*[mesh.ufl_cell() for mesh in meshes])
 
         # TODO: Is this what we want to do?
         # Build coordinate element from mesh coordinate elements
@@ -221,13 +238,15 @@ class TensorProductMesh(AbstractDomain):
         return self._ufl_cell
 
     def is_piecewise_linear_simplex_domain(self):
-        return False # TODO: Any cases this is True
+        return False  # TODO: Any cases this is True
 
     def __repr__(self):
-        return "TensorProductMesh(%r, %r)" % (self._ufl_meshes, self._ufl_id)
+        r = "TensorProductMesh(%s, %s)" % (repr(self._ufl_meshes), repr(self._ufl_id))
+        return as_native_str(r)
 
     def __str__(self):
-        return "<TensorProductMesh #%s with meshes %s>" % (self._ufl_id, self._ufl_meshes)
+        return "<TensorProductMesh #%s with meshes %s>" % (
+            self._ufl_id, self._ufl_meshes)
 
     def _ufl_hash_data_(self):
         return (self._ufl_id,) + tuple(mesh._ufl_hash_data_() for mesh in self._ufl_meshes)
@@ -235,10 +254,12 @@ class TensorProductMesh(AbstractDomain):
     def _ufl_signature_data_(self, renumbering):
         return ("TensorProductMesh",) + tuple(mesh._ufl_signature_data_(renumbering) for mesh in self._ufl_meshes)
 
-    # NB! Dropped __lt__ here, don't want users to write 'mesh1 < mesh2'.
+    # NB! Dropped __lt__ here, don't want users to write 'mesh1 <
+    # mesh2'.
     def _ufl_sort_key_(self):
         typespecific = (self._ufl_id, tuple(mesh._ufl_sort_key_() for mesh in self._ufl_meshes))
-        return (self.geometric_dimension(), self.topological_dimension(), "TensorProductMesh", typespecific)
+        return (self.geometric_dimension(), self.topological_dimension(),
+                "TensorProductMesh", typespecific)
 
 
 # --- Utility conversion functions
@@ -252,42 +273,48 @@ def affine_mesh(cell, ufl_id=None):
     coordinate_element = VectorElement("Lagrange", cell, degree, dim=gdim)
     return Mesh(coordinate_element, ufl_id=ufl_id)
 
+
 _default_domains = {}
+
+
 def default_domain(cell):
     "Create a singular default Mesh from a cell, always returning the same Mesh object for the same cell."
     global _default_domains
     assert isinstance(cell, AbstractCell)
     domain = _default_domains.get(cell)
     if domain is None:
-        # Create one and only one affine Mesh with
-        # a negative ufl_id to avoid id collision
+        # Create one and only one affine Mesh with a negative ufl_id
+        # to avoid id collision
         ufl_id = -(len(_default_domains)+1)
         domain = affine_mesh(cell, ufl_id=ufl_id)
         _default_domains[cell] = domain
     return domain
 
+
 def as_domain(domain):
     """Convert any valid object to an AbstractDomain type."""
     if isinstance(domain, AbstractDomain):
         # Modern .ufl files and dolfin behaviour
         return domain
     elif hasattr(domain, "ufl_domain"):
-        # If we get a dolfin.Mesh, it can provide us a corresponding ufl.Mesh.
-        # This would be unnecessary if dolfin.Mesh could subclass ufl.Mesh.
+        # If we get a dolfin.Mesh, it can provide us a corresponding
+        # ufl.Mesh.  This would be unnecessary if dolfin.Mesh could
+        # subclass ufl.Mesh.
         return domain.ufl_domain()
     else:
         # Legacy .ufl files
-        # TODO: Make this conversion in the relevant constructors closer to the user interface?
+        # TODO: Make this conversion in the relevant constructors
+        # closer to the user interface?
         # TODO: Make this configurable to be an error from the dolfin side?
         cell = as_cell(domain)
         return default_domain(cell)
-    #else:
-    #    error("Invalid domain %s" % (domain,))
+
 
 def sort_domains(domains):
     "Sort domains in a canonical ordering."
     return tuple(sorted(domains, key=lambda domain: domain._ufl_sort_key_()))
 
+
 def join_domains(domains):
     """Take a list of domains and return a tuple with only unique domain objects.
 
@@ -338,6 +365,7 @@ def extract_domains(expr):
         domainlist.extend(t.ufl_domains())
     return sorted(join_domains(domainlist))
 
+
 def extract_unique_domain(expr):
     "Return the single unique domain expression is defined on or throw an error."
     domains = extract_domains(expr)
@@ -346,9 +374,9 @@ def extract_unique_domain(expr):
     elif domains:
         error("Found multiple domains, cannot return just one.")
     else:
-        #error("Found no domains.")
         return None
 
+
 def find_geometric_dimension(expr):
     "Find the geometric dimension of an expression."
     gdims = set()
diff --git a/ufl/equation.py b/ufl/equation.py
index 4c6df8b..63e4a1d 100644
--- a/ufl/equation.py
+++ b/ufl/equation.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "The Equation class, used to express equations like a == L."
 
-# Copyright (C) 2012-2015 Anders Logg and Martin Sandve Alnæs
+# Copyright (C) 2012-2016 Anders Logg and Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,8 +18,13 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+from ufl.log import error
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
+
 # Export list for ufl.classes
-__all_classes__ = ["Equation"]
+__all_classes__ = as_native_strings(["Equation"])
+
 
 class Equation(object):
     """This class is used to represent equations expressed by the "=="
@@ -39,14 +44,17 @@ class Equation(object):
         """
         # NB!: pep8 will say you should use isinstance here, but we do
         #      actually want to compare the exact types in this case.
-        # Not equal if types are not identical (i.e. not accepting subclasses)
-        if type(self.lhs) != type(self.rhs):
+        # Not equal if types are not identical (i.e. not accepting
+        # subclasses)
+        if type(self.lhs) != type(self.rhs):  # noqa: E721
             return False
         # Try to delegate to equals function
         if hasattr(self.lhs, "equals"):
             return self.lhs.equals(self.rhs)
-        # Fall back to repr
-        return repr(self.lhs) == repr(self.rhs)
+        elif hasattr(self.rhs, "equals"):
+            return self.rhs.equals(self.lhs)
+        else:
+            error("Either lhs or rhs of Equation must implement self.equals(other).")
     __nonzero__ = __bool__
 
     def __eq__(self, other):
@@ -59,4 +67,5 @@ class Equation(object):
         return hash((hash(self.lhs), hash(self.rhs)))
 
     def __repr__(self):
-        return "Equation(%r, %r)" % (self.lhs, self.rhs)
+        r = "Equation(%s, %s)" % (repr(self.lhs), repr(self.rhs))
+        return as_native_str(r)
diff --git a/ufl/exprcontainers.py b/ufl/exprcontainers.py
index 654978c..f44fd82 100644
--- a/ufl/exprcontainers.py
+++ b/ufl/exprcontainers.py
@@ -18,14 +18,14 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
-from ufl.utils.dicts import EmptyDict
+from ufl.utils.py23 import as_native_str
+from ufl.log import error
 from ufl.core.expr import Expr
 from ufl.core.operator import Operator
 from ufl.core.ufl_type import ufl_type
 
-#--- Non-tensor types ---
+
+# --- Non-tensor types ---
 
 @ufl_type(num_ops="varying")
 class ExprList(Operator):
@@ -50,7 +50,8 @@ class ExprList(Operator):
         return "ExprList(*(%s,))" % ", ".join(str(i) for i in self.ufl_operands)
 
     def __repr__(self):
-        return "ExprList(*%r)" % (self.ufl_operands,)
+        r = "ExprList(*%s)" % repr(self.ufl_operands)
+        return as_native_str(r)
 
     @property
     def ufl_shape(self):
@@ -82,26 +83,28 @@ class ExprMapping(Operator):
             error("Expecting Expr in ExprMapping.")
 
     def ufl_domains(self):
-        # Because this type can act like a terminal if it has no operands, we need to override some recursive operations
+        # Because this type can act like a terminal if it has no
+        # operands, we need to override some recursive operations
         if self.ufl_operands:
             return Operator.ufl_domains()
         else:
             return []
 
-    #def __getitem__(self, key):
-    #    return self.ufl_operands[key]
+    # def __getitem__(self, key):
+    #     return self.ufl_operands[key]
 
-    #def __len__(self):
-    #    return len(self.ufl_operands) // 2
+    # def __len__(self):
+    #     return len(self.ufl_operands) // 2
 
-    #def __iter__(self):
-    #    return iter(self.ufl_operands[::2])
+    # def __iter__(self):
+    #     return iter(self.ufl_operands[::2])
 
     def __str__(self):
-        return "ExprMapping(*%r)" % (self.ufl_operands,)
+        return "ExprMapping(*%s)" % repr(self.ufl_operands)
 
     def __repr__(self):
-        return "ExprMapping(*%r)" % (self.ufl_operands,)
+        r = "ExprMapping(*%s)" % repr(self.ufl_operands)
+        return as_native_str(r)
 
     @property
     def ufl_shape(self):
diff --git a/ufl/exprequals.py b/ufl/exprequals.py
index 34c50f8..9267abc 100644
--- a/ufl/exprequals.py
+++ b/ufl/exprequals.py
@@ -5,15 +5,13 @@ from six.moves import zip
 
 from ufl.core.expr import Expr
 from ufl.log import error
-from ufl.core.operator import Operator
-from ufl.core.terminal import Terminal
-from ufl.corealg.traversal import pre_traversal
-
 
 hash_total = defaultdict(int)
 hash_collisions = defaultdict(int)
 hash_equals = defaultdict(int)
 hash_notequals = defaultdict(int)
+
+
 def print_collisions():
 
     keys = sorted(hash_total.keys(), key=lambda x: (hash_collisions[x], x))
@@ -32,9 +30,9 @@ def print_collisions():
         if sn != on and ne == tot:
             continue
         print(fmt % (k, eq, int(100.0*eq/tot),
-                            ne, int(100.0*ne/tot),
-                            co, int(100.0*co/tot),
-                            tot))
+                     ne, int(100.0*ne/tot),
+                     co, int(100.0*co/tot),
+                     tot))
 
 
 def measure_collisions(equals_func):
@@ -51,7 +49,8 @@ def measure_collisions(equals_func):
         oh = hash(other)
         key = (sn, on)
 
-        # If hashes are the same but objects are not equal, we have a collision
+        # If hashes are the same but objects are not equal, we have a
+        # collision
         hash_total[key] += 1
         if sh == oh and not equal:
             hash_collisions[key] += 1
@@ -66,8 +65,8 @@ def measure_collisions(equals_func):
     return equals_func_with_collision_measuring
 
 
-#@measure_collisions
-def recursive_expr_equals(self, other): # Much faster than the more complex algorithms above!
+# @measure_collisions
+def recursive_expr_equals(self, other):  # Much faster than the more complex algorithms above!
     """Checks whether the two expressions are represented the
     exact same way. This does not check if the expressions are
     mathematically equal or equivalent! Used by sets and dicts."""
@@ -90,25 +89,29 @@ def recursive_expr_equals(self, other): # Much faster than the more complex algo
 
     # Terminals
     if self._ufl_is_terminal_:
-        # Compare terminals with custom == to capture subclass overloading of __eq__
+        # Compare terminals with custom == to capture subclass
+        # overloading of __eq__
         return self == other
 
-    # --- Operators, most likely equal, below here is the costly part if it recurses through a large tree! ---
+    # --- Operators, most likely equal, below here is the costly part
+    # --- if it recurses through a large tree! ---
 
-    # Recurse manually to call expr_equals directly without the class EQ overhead!
-    equal = all(recursive_expr_equals(a, b) for (a, b) in zip(self.ufl_operands, other.ufl_operands))
+    # Recurse manually to call expr_equals directly without the class
+    # EQ overhead!
+    equal = all(recursive_expr_equals(a, b) for (a, b) in zip(self.ufl_operands,
+                                                              other.ufl_operands))
 
     return equal
 
 
-#@measure_collisions
+# @measure_collisions
 def nonrecursive_expr_equals(self, other):
     """Checks whether the two expressions are represented the
     exact same way. This does not check if the expressions are
     mathematically equal or equivalent! Used by sets and dicts."""
 
-    # Fast cutoffs for common cases, type difference or
-    # hash difference will cutoff more or less all nonequal types
+    # Fast cutoffs for common cases, type difference or hash
+    # difference will cutoff more or less all nonequal types
     if type(self) != type(other) or hash(self) != hash(other):
         return False
 
@@ -145,5 +148,6 @@ def nonrecursive_expr_equals(self, other):
     # Equal if we get out of the above loop!
     return True
 
-#expr_equals = recursive_expr_equals
+
+# expr_equals = recursive_expr_equals
 expr_equals = nonrecursive_expr_equals
diff --git a/ufl/exproperators.py b/ufl/exproperators.py
index 99a1234..77920ae 100644
--- a/ufl/exproperators.py
+++ b/ufl/exproperators.py
@@ -3,7 +3,7 @@
 This way we avoid circular dependencies between e.g.
 Sum and its superclass Expr."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,15 +19,15 @@ Sum and its superclass Expr."""
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016.
 
 from itertools import chain
+import numbers
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
-from ufl.utils.dicts import mergedicts, subdict
 from ufl.utils.stacks import StackDict
 from ufl.core.expr import Expr
-from ufl.core.operator import Operator
 from ufl.constantvalue import Zero, as_ufl
 from ufl.algebra import Sum, Product, Division, Power, Abs
 from ufl.tensoralgebra import Transposed, Inner
@@ -39,44 +39,52 @@ from ufl.restriction import PositiveRestricted, NegativeRestricted
 from ufl.differentiation import Grad
 from ufl.index_combination_utils import create_slice_indices, merge_overlapping_indices
 
+from ufl.exprequals import expr_equals
+
+# --- Boolean operators ---
 
-#--- Boolean operators ---
+from ufl.conditional import LE, GE, LT, GT
 
-from ufl.conditional import EQ, NE, LE, GE, LT, GT
 
 def _le(left, right):
     "UFL operator: A boolean expresion (left <= right) for use with conditional."
     return LE(left, right)
 
+
 def _ge(left, right):
     "UFL operator: A boolean expresion (left >= right) for use with conditional."
     return GE(left, right)
 
+
 def _lt(left, right):
     "UFL operator: A boolean expresion (left < right) for use with conditional."
     return LT(left, right)
 
+
 def _gt(left, right):
     "UFL operator: A boolean expresion (left > right) for use with conditional."
     return GT(left, right)
 
 
-# '==' needs to implement comparison of expression representations for use in
-# hashmaps (dict and set), but the others can be overloaded in the language.
-# It is possible that we can overload eq as well, but we'll need to fix some
-# issues first and also check for a possible significant performance hit with
-# compilation of complex forms. Replacing a==b with equiv(a,b) all over the
-# code could be one way to reduce such a performance hit, but we cannot do
-# anything about dict and set calling __eq__...
-from ufl.exprequals import expr_equals
+# '==' needs to implement comparison of expression representations for
+# use in hashmaps (dict and set), but the others can be overloaded in
+# the language.  It is possible that we can overload eq as well, but
+# we'll need to fix some issues first and also check for a possible
+# significant performance hit with compilation of complex
+# forms. Replacing a==b with equiv(a,b) all over the code could be one
+# way to reduce such a performance hit, but we cannot do anything
+# about dict and set calling __eq__...
 Expr.__eq__ = expr_equals
 
-# != is used at least by tests, possibly in code as well, and must mean
-# the opposite of ==, i.e. when evaluated as bool it must mean 'not equal representation'.
+
+# != is used at least by tests, possibly in code as well, and must
+# mean the opposite of ==, i.e. when evaluated as bool it must mean
+# 'not equal representation'.
 def _ne(self, other):
     return not self.__eq__(other)
-Expr.__ne__ = _ne
 
+
+Expr.__ne__ = _ne
 Expr.__lt__ = _lt
 Expr.__gt__ = _gt
 Expr.__le__ = _le
@@ -84,8 +92,9 @@ Expr.__ge__ = _ge
 
 # Python operators 'and'/'or' cannot be overloaded, and bitwise
 # operators &/| don't have the right precedence levels
-#Expr.__and__ = _and
-#Expr.__or__ = _or
+# Expr.__and__ = _and
+# Expr.__or__ = _or
+
 
 def _as_tensor(self, indices):
     "UFL operator: A^indices := as_tensor(A, indices)."
@@ -97,7 +106,7 @@ def _as_tensor(self, indices):
 Expr.__xor__ = _as_tensor
 
 
-#--- Helper functions for product handling ---
+# --- Helper functions for product handling ---
 
 def _mult(a, b):
     # Discover repeated indices, which results in index sums
@@ -129,14 +138,15 @@ def _mult(a, b):
             return Zero(shape, fi, fid)
 
         # Repeated indices are allowed, like in:
-        #v[i]*M[i,:]
+        # v[i]*M[i,:]
 
         # Apply product to scalar components
         ti = indices(len(b.ufl_shape))
         p = Product(a, b[ti])
 
-    elif r1 == 2 and r2 in (1, 2): # Matrix-matrix or matrix-vector
-        ufl_assert(not ri, "Not expecting repeated indices in non-scalar product.")
+    elif r1 == 2 and r2 in (1, 2):  # Matrix-matrix or matrix-vector
+        if ri:
+            error("Not expecting repeated indices in non-scalar product.")
 
         # Check for zero, simplifying early if possible
         if isinstance(a, Zero) or isinstance(b, Zero):
@@ -154,21 +164,24 @@ def _mult(a, b):
     else:
         error("Invalid ranks {0} and {1} in product.".format(r1, r2))
 
-    # TODO: I think applying as_tensor after index sums results in cleaner expression graphs.
+    # TODO: I think applying as_tensor after index sums results in
+    # cleaner expression graphs.
     # Wrap as tensor again
     if ti:
         p = as_tensor(p, ti)
 
-    # If any repeated indices were found, apply implicit summation over those
+    # If any repeated indices were found, apply implicit summation
+    # over those
     for i in ri:
         mi = MultiIndex((Index(count=i),))
         p = IndexSum(p, mi)
 
     return p
 
-#--- Extend Expr with algebraic operators ---
+# --- Extend Expr with algebraic operators ---
+
+_valid_types = (Expr, numbers.Real, numbers.Integral)
 
-_valid_types = (Expr,) + (int, float)
 
 def _mul(self, o):
     if not isinstance(o, _valid_types):
@@ -177,6 +190,7 @@ def _mul(self, o):
     return _mult(self, o)
 Expr.__mul__ = _mul
 
+
 def _rmul(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
@@ -184,33 +198,39 @@ def _rmul(self, o):
     return _mult(o, self)
 Expr.__rmul__ = _rmul
 
+
 def _add(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
     return Sum(self, o)
 Expr.__add__ = _add
 
+
 def _radd(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
-    if isinstance(o, int) and o == 0:
-        # Allow adding scalar int 0 as a no-op, even for shaped self, needed for sum([a,b])
+    if isinstance(o, numbers.Number) and o == 0:
+        # Allow adding scalar int 0 as a no-op, even for shaped self,
+        # needed for sum([a,b])
         return self
     return Sum(o, self)
 Expr.__radd__ = _radd
 
+
 def _sub(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
     return Sum(self, -o)
 Expr.__sub__ = _sub
 
+
 def _rsub(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
     return Sum(o, -self)
 Expr.__rsub__ = _rsub
 
+
 def _div(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
@@ -223,6 +243,7 @@ def _div(self, o):
 Expr.__div__ = _div
 Expr.__truediv__ = _div
 
+
 def _rdiv(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
@@ -230,6 +251,7 @@ def _rdiv(self, o):
 Expr.__rdiv__ = _rdiv
 Expr.__rtruediv__ = _rdiv
 
+
 def _pow(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
@@ -238,33 +260,38 @@ def _pow(self, o):
     return Power(self, o)
 Expr.__pow__ = _pow
 
+
 def _rpow(self, o):
     if not isinstance(o, _valid_types):
         return NotImplemented
     return Power(o, self)
 Expr.__rpow__ = _rpow
 
+
 # TODO: Add Negated class for this? Might simplify reductions in Add.
 def _neg(self):
     return -1*self
 Expr.__neg__ = _neg
 
+
 def _abs(self):
     return Abs(self)
 Expr.__abs__ = _abs
 
-#--- Extend Expr with restiction operators a("+"), a("-") ---
+
+# --- Extend Expr with restiction operators a("+"), a("-") ---
 
 def _restrict(self, side):
     if side == "+":
         return PositiveRestricted(self)
     if side == "-":
         return NegativeRestricted(self)
-    error("Invalid side %r in restriction operator." % side)
+    error("Invalid side '%s' in restriction operator." % (side,))
+
 
 def _eval(self, coord, mapping=None, component=()):
-    # Evaluate expression at this particular coordinate,
-    # with provided values for other terminals in mapping
+    # Evaluate expression at this particular coordinate, with provided
+    # values for other terminals in mapping
 
     # Evaluate derivatives first
     from ufl.algorithms import expand_derivatives
@@ -276,24 +303,28 @@ def _eval(self, coord, mapping=None, component=()):
     index_values = StackDict()
     return f.evaluate(coord, mapping, component, index_values)
 
+
 def _call(self, arg, mapping=None, component=()):
     # Taking the restriction or evaluating depending on argument
     if arg in ("+", "-"):
-        ufl_assert(mapping is None, "Not expecting a mapping when taking restriction.")
+        if mapping is not None:
+            error("Not expecting a mapping when taking restriction.")
         return _restrict(self, arg)
     else:
         return _eval(self, arg, mapping, component)
 Expr.__call__ = _call
 
-#--- Extend Expr with the transpose operation A.T ---
+
+# --- Extend Expr with the transpose operation A.T ---
 
 def _transpose(self):
-    """Transposed a rank two tensor expression. For more general transpose
+    """Transpose a rank-2 tensor expression. For more general transpose
     operations of higher order tensor expressions, use indexing and Tensor."""
     return Transposed(self)
 Expr.T = property(_transpose)
 
-#--- Extend Expr with indexing operator a[i] ---
+
+# --- Extend Expr with indexing operator a[i] ---
 
 def analyse_key(ii, rank):
     """Takes something the user might input as an index tuple
@@ -318,7 +349,8 @@ def analyse_key(ii, rank):
     if not isinstance(ii, (tuple, MultiIndex)):
         ii = (ii,)
     else:
-        # Flatten nested tuples, happens with f[...,ii] where ii is a tuple of indices
+        # Flatten nested tuples, happens with f[...,ii] where ii is a
+        # tuple of indices
         jj = []
         for j in ii:
             if isinstance(j, (tuple, MultiIndex)):
@@ -327,20 +359,22 @@ def analyse_key(ii, rank):
                 jj.append(j)
         ii = tuple(jj)
 
-    # Convert all indices to Index or FixedIndex objects.
-    # If there is an ellipsis, split the indices into before and after.
+    # Convert all indices to Index or FixedIndex objects.  If there is
+    # an ellipsis, split the indices into before and after.
     axis_indices = set()
-    pre  = []
+    pre = []
     post = []
     indexlist = pre
     for i in ii:
         if i == Ellipsis:
-            # Switch from pre to post list when an ellipsis is encountered
-            ufl_assert(indexlist is pre, "Found duplicate ellipsis.")
+            # Switch from pre to post list when an ellipsis is
+            # encountered
+            if indexlist is not pre:
+                error("Found duplicate ellipsis.")
             indexlist = post
         else:
             # Convert index to a proper type
-            if isinstance(i, int):
+            if isinstance(i, numbers.Integral):
                 idx = FixedIndex(i)
             elif isinstance(i, IndexBase):
                 idx = i
@@ -352,13 +386,13 @@ def analyse_key(ii, rank):
                     # TODO: Use ListTensor to support partial slices?
                     error("Partial slices not implemented, only complete slices like [:]")
             else:
-                error("Can't convert this object to index: %r" % i)
+                error("Can't convert this object to index: %s" % (i,))
 
             # Store index in pre or post list
             indexlist.append(idx)
 
-    # Handle ellipsis as a number of complete slices,
-    # that is create a number of new axis indices
+    # Handle ellipsis as a number of complete slices, that is create a
+    # number of new axis indices
     num_axis = rank - len(pre) - len(post)
     if indexlist is post:
         ellipsis_indices = indices(num_axis)
@@ -371,6 +405,7 @@ def analyse_key(ii, rank):
     axis_indices = tuple(i for i in all_indices if i in axis_indices)
     return all_indices, axis_indices
 
+
 def _getitem(self, component):
 
     # Treat component consistently as tuple below
@@ -382,11 +417,13 @@ def _getitem(self, component):
     # Analyse slices (:) and Ellipsis (...)
     all_indices, slice_indices, repeated_indices = create_slice_indices(component, shape, self.ufl_free_indices)
 
-    # Check that we have the right number of indices for a tensor with this shape
+    # Check that we have the right number of indices for a tensor with
+    # this shape
     if len(shape) != len(all_indices):
         error("Invalid number of indices {0} for expression of rank {1}.".format(len(all_indices), len(shape)))
 
-    # Special case for simplifying foo[...] => foo, foo[:] => foo or similar
+    # Special case for simplifying foo[...] => foo, foo[:] => foo or
+    # similar
     if len(slice_indices) == len(all_indices):
         return self
 
@@ -395,23 +432,27 @@ def _getitem(self, component):
         if all_indices == self.indices().indices():
             return self.ufl_operands[0]
 
-    # Apply all indices to index self, yielding a scalar valued expression
+    # Apply all indices to index self, yielding a scalar valued
+    # expression
     mi = MultiIndex(all_indices)
     a = Indexed(self, mi)
 
-    # TODO: I think applying as_tensor after index sums results in cleaner expression graphs.
+    # TODO: I think applying as_tensor after index sums results in
+    # cleaner expression graphs.
 
-    # If the Ellipsis or any slices were found, wrap as tensor
-    # valued with the slice indices created at the top here
+    # If the Ellipsis or any slices were found, wrap as tensor valued
+    # with the slice indices created at the top here
     if slice_indices:
         a = as_tensor(a, slice_indices)
 
-    # If any repeated indices were found, apply implicit summation over those
+    # If any repeated indices were found, apply implicit summation
+    # over those
     for i in repeated_indices:
         mi = MultiIndex((i,))
         a = IndexSum(a, mi)
 
-    # Check for zero (last so we can get indices etc from a, could possibly be done faster by checking early instead)
+    # Check for zero (last so we can get indices etc from a, could
+    # possibly be done faster by checking early instead)
     if isinstance(self, Zero):
         shape = a.ufl_shape
         fi = a.ufl_free_indices
@@ -422,10 +463,11 @@ def _getitem(self, component):
 
 Expr.__getitem__ = _getitem
 
-#--- Extend Expr with spatial differentiation operator a.dx(i) ---
+
+# --- Extend Expr with spatial differentiation operator a.dx(i) ---
 
 def _dx(self, *ii):
-    "Return the partial derivative with respect to spatial variable number i."
+    "Return the partial derivative with respect to spatial variable number *ii*."
     d = self
     # Unwrap ii to allow .dx(i,j) and .dx((i,j))
     if len(ii) == 1 and isinstance(ii[0], tuple):
@@ -433,6 +475,7 @@ def _dx(self, *ii):
     # Apply all derivatives
     for i in ii:
         d = Grad(d)
+
     # Take all components, applying repeated index sums in the [] operation
     return d.__getitem__((Ellipsis,) + ii)
 
diff --git a/ufl/finiteelement/__init__.py b/ufl/finiteelement/__init__.py
index 2b65f9a..3499046 100644
--- a/ufl/finiteelement/__init__.py
+++ b/ufl/finiteelement/__init__.py
@@ -1,7 +1,8 @@
 # -*- coding: utf-8 -*-
+# flake8: noqa
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -31,10 +32,8 @@ from ufl.finiteelement.mixedelement import TensorElement
 from ufl.finiteelement.enrichedelement import EnrichedElement
 from ufl.finiteelement.restrictedelement import RestrictedElement
 from ufl.finiteelement.tensorproductelement import TensorProductElement
-from ufl.finiteelement.outerproductelement import OuterProductElement
 from ufl.finiteelement.hdivcurl import HDivElement, HCurlElement
 from ufl.finiteelement.brokenelement import BrokenElement
-from ufl.finiteelement.traceelement import TraceElement
 from ufl.finiteelement.facetelement import FacetElement
 from ufl.finiteelement.interiorelement import InteriorElement
 
@@ -48,11 +47,9 @@ __all_classes__ = [
     "EnrichedElement",
     "RestrictedElement",
     "TensorProductElement",
-    "OuterProductElement",
     "HDivElement",
     "HCurlElement",
     "BrokenElement",
-    "TraceElement",
     "FacetElement",
     "InteriorElement",
     ]
diff --git a/ufl/finiteelement/brokenelement.py b/ufl/finiteelement/brokenelement.py
index b0fbc8d..7bc2e92 100644
--- a/ufl/finiteelement/brokenelement.py
+++ b/ufl/finiteelement/brokenelement.py
@@ -15,15 +15,20 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
+# import six
+from ufl.utils.py23 import as_native_str
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
 
+# @six.python_2_unicode_compatible
 class BrokenElement(FiniteElementBase):
-    """The discontinuous version of an existing Finite Element space"""
+    """The discontinuous version of an existing Finite Element space."""
     def __init__(self, element):
         self._element = element
-        self._repr = "BrokenElement(%r)" % (element,)
+        self._repr = as_native_str("BrokenElement(%s)" % repr(element))
 
         family = "BrokenElement"
         cell = element.cell()
@@ -41,7 +46,5 @@ class BrokenElement(FiniteElementBase):
         return "BrokenElement(%s)" % str(self._element)
 
     def shortstr(self):
+        "Format as string for pretty printing."
         return "BrokenElement(%s)" % str(self._element.shortstr())
-
-    def __repr__(self):
-        return self._repr
diff --git a/ufl/finiteelement/elementlist.py b/ufl/finiteelement/elementlist.py
index 950ff8c..07cb7f2 100644
--- a/ufl/finiteelement/elementlist.py
+++ b/ufl/finiteelement/elementlist.py
@@ -1,9 +1,9 @@
 # -*- coding: utf-8 -*-
 """This module provides an extensive list of predefined finite element
-families. Users or more likely, form compilers, may register new
+families. Users or, more likely, form compilers, may register new
 elements by calling the function register_element."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -21,14 +21,16 @@ elements by calling the function register_element."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Marie E. Rognes <meg at simula.no>, 2010
-# Modified by Lizao Li <lzlarryli at gmail.com>, 2015
+# Modified by Lizao Li <lzlarryli at gmail.com>, 2015, 2016
+# Modified by Massimiliano Leoni, 2016
 
 from __future__ import print_function
 
-from ufl.assertions import ufl_assert
-from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl, HEin
+from ufl.log import warning, error
+from ufl.sobolevspace import L2, H1, H2, HDiv, HCurl, HEin, HDivDiv
 from ufl.utils.formatting import istr
-from ufl.cell import Cell
+from ufl.cell import Cell, TensorProductCell
+
 
 # List of valid elements
 ufl_elements = {}
@@ -36,22 +38,34 @@ ufl_elements = {}
 # Aliases: aliases[name] (...) -> (standard_name, ...)
 aliases = {}
 
+
 # Function for registering new elements
-def register_element(family, short_name, value_rank, sobolev_space, mapping, degree_range, cellnames):
-    "Register new finite element family"
-    ufl_assert(family not in ufl_elements, 'Finite element \"%s\" has already been registered.' % family)
-    ufl_elements[family]     = (family, short_name, value_rank, sobolev_space, mapping, degree_range, cellnames)
-    ufl_elements[short_name] = (family, short_name, value_rank, sobolev_space, mapping, degree_range, cellnames)
+def register_element(family, short_name, value_rank, sobolev_space, mapping,
+                     degree_range, cellnames):
+    "Register new finite element family."
+    if family in ufl_elements:
+        error('Finite element \"%s\" has already been registered.' % family)
+    ufl_elements[family] = (family, short_name, value_rank, sobolev_space,
+                            mapping, degree_range, cellnames)
+    ufl_elements[short_name] = (family, short_name, value_rank, sobolev_space,
+                                mapping, degree_range, cellnames)
+
+
+def register_element2(family, value_rank, sobolev_space, mapping,
+                      degree_range, cellnames):
+    "Register new finite element family."
+    if family in ufl_elements:
+        error('Finite element \"%s\" has already been registered.' % family)
+    ufl_elements[family] = (family, family, value_rank, sobolev_space,
+                            mapping, degree_range, cellnames)
 
-def register_element2(family, value_rank, sobolev_space, mapping, degree_range, cellnames):
-    "Register new finite element family"
-    ufl_assert(family not in ufl_elements, 'Finite element \"%s\" has already been registered.' % family)
-    ufl_elements[family] = (family, family, value_rank, sobolev_space, mapping, degree_range, cellnames)
 
 def register_alias(alias, to):
     aliases[alias] = to
 
+
 def show_elements():
+    "Shows all registered elements."
     print("Showing all registered elements:")
     print("================================")
     shown = set()
@@ -61,7 +75,7 @@ def show_elements():
             continue
         shown.add(data)
         (family, short_name, value_rank, sobolev_space, mapping, degree_range, cellnames) = data
-        print("Finite element family: %s, %s" % (repr(family), repr(short_name)))
+        print("Finite element family: '%s', '%s'" % (family, short_name))
         print("Sobolev space: %s" % (sobolev_space,))
         print("Mapping: %s" % (mapping,))
         print("Degree range: %s" % (degree_range,))
@@ -69,9 +83,11 @@ def show_elements():
         print("Defined on cellnames: %s" % (cellnames,))
         print()
 
-# FIXME: Consider cleanup of element names. Use notation from periodic table as the main, keep old names as compatibility aliases.
+# FIXME: Consider cleanup of element names. Use notation from periodic
+# table as the main, keep old names as compatibility aliases.
 
-# NOTE: Any element with polynomial degree 0 will be considered L2, independent of the space passed to register_element.
+# NOTE: Any element with polynomial degree 0 will be considered L2,
+# independent of the space passed to register_element.
 
 # NOTE: The mapping of the element basis functions
 #       from reference to physical representation is
@@ -80,46 +96,73 @@ def show_elements():
 #       HCurl = covariant Piola,
 #       H1/L2 = no mapping.
 
-# TODO: If determining mapping from sobolev_space isn't sufficient
-#       in the future, add mapping name as another element property.
+# TODO: If determining mapping from sobolev_space isn't sufficient in
+#       the future, add mapping name as another element property.
 
 # Cell groups
 simplices = ("interval", "triangle", "tetrahedron")
-cubes     = ("interval", "quadrilateral", "hexahedron")
-any_cell  = (None,
-             "vertex", "interval",
-             "triangle", "tetrahedron",
-             "quadrilateral", "hexahedron")
-
-# Elements in the periodic table # TODO: Register these as aliases of periodic table element description instead of the other way around
-register_element("Lagrange", "CG",                       0, H1,    "identity", (1, None), any_cell)                  # "P"
-register_element("Brezzi-Douglas-Marini", "BDM",         1, HDiv,  "contravariant Piola", (1, None), simplices[1:])  # "BDMF" (2d), "N2F" (3d)
-register_element("Discontinuous Lagrange", "DG",         0, L2,    "identity", (0, None), any_cell)                  # "DP"
-register_element("Nedelec 1st kind H(curl)", "N1curl",   1, HCurl, "covariant Piola", (1, None), simplices[1:])      # "RTE"  (2d), "N1E" (3d)
-register_element("Nedelec 2nd kind H(curl)", "N2curl",   1, HCurl, "covariant Piola", (1, None), simplices[1:])      # "BDME" (2d), "N2E" (3d)
-register_element("Raviart-Thomas", "RT",                 1, HDiv,  "contravariant Piola", (1, None), simplices[1:])  # "RTF"  (2d), "N1F" (3d)
+cubes = ("interval", "quadrilateral", "hexahedron")
+any_cell = (None,
+            "vertex", "interval",
+            "triangle", "tetrahedron",
+            "quadrilateral", "hexahedron")
+
+# Elements in the periodic table # TODO: Register these as aliases of
+# periodic table element description instead of the other way around
+register_element("Lagrange", "CG", 0, H1, "identity", (1, None),
+                 any_cell)  # "P"
+register_element("Brezzi-Douglas-Marini", "BDM", 1, HDiv,
+                 "contravariant Piola", (1, None), simplices[1:])  # "BDMF" (2d), "N2F" (3d)
+register_element("Discontinuous Lagrange", "DG", 0, L2, "identity", (0, None),
+                 any_cell)  # "DP"
+register_element("Discontinuous Taylor", "TDG", 0, L2, "identity", (0, None), simplices)
+register_element("Nedelec 1st kind H(curl)", "N1curl", 1, HCurl,
+                 "covariant Piola", (1, None), simplices[1:])  # "RTE"  (2d), "N1E" (3d)
+register_element("Nedelec 2nd kind H(curl)", "N2curl", 1, HCurl,
+                 "covariant Piola", (1, None), simplices[1:])  # "BDME" (2d), "N2E" (3d)
+register_element("Raviart-Thomas", "RT", 1, HDiv, "contravariant Piola",
+                 (1, None), simplices[1:])   # "RTF"  (2d), "N1F" (3d)
 
 # Elements not in the periodic table
-register_element("Argyris", "ARG",                       0, H2,   "identity", (1, None), simplices[1:])
-register_element("Arnold-Winther", "AW",                 0, H1,   "identity", None, ("triangle",))
-register_element("Brezzi-Douglas-Fortin-Marini", "BDFM", 1, HDiv, "contravariant Piola", (1, None), simplices[1:])
-register_element("Crouzeix-Raviart", "CR",               0, L2,   "identity", (1, 1), simplices[1:])
+register_element("Argyris", "ARG", 0, H2, "identity", (1, None), simplices[1:])
+register_element("Arnold-Winther", "AW", 0, H1, "identity", None, ("triangle",))
+register_element("Brezzi-Douglas-Fortin-Marini", "BDFM", 1, HDiv,
+                 "contravariant Piola", (1, None), simplices[1:])
+register_element("Crouzeix-Raviart", "CR", 0, L2, "identity", (1, 1),
+                 simplices[1:])
 # TODO: Implement generic Tear operator for elements instead of this:
-register_element("Discontinuous Raviart-Thomas", "DRT",  1, L2,   "contravariant Piola", (1, None), simplices[1:])
-register_element("Hermite", "HER",                       0, H1,   "identity", None, simplices[1:])
-register_element("Mardal-Tai-Winther", "MTW",            0, H1,   "identity", None, ("triangle",))
-register_element("Morley", "MOR",                        0, H2,   "identity", None, ("triangle",))
+register_element("Discontinuous Raviart-Thomas", "DRT", 1, L2,
+                 "contravariant Piola", (1, None), simplices[1:])
+register_element("Hermite", "HER", 0, H1, "identity", None, simplices[1:])
+register_element("Mardal-Tai-Winther", "MTW", 0, H1, "identity", None,
+                 ("triangle",))
+register_element("Morley", "MOR", 0, H2, "identity", None, ("triangle",))
 
 # Special elements
-register_element("Boundary Quadrature", "BQ", 0, L2, "identity", (0, None), any_cell)
-register_element("Bubble", "B",               0, H1, "identity", (2, None), simplices)
-register_element("Quadrature", "Quadrature",  0, L2, "identity", (0, None), any_cell)
-register_element("Real", "R",                 0, L2, "identity", (0, 0),    any_cell + ("OuterProductCell",))
-register_element("Undefined", "U",            0, L2, "identity", (0, None), any_cell)
-register_element("Lobatto", "Lob",            0, L2, "identity", (1, None), ("interval",))
-register_element("Radau",   "Rad",            0, L2, "identity", (0, None), ("interval",))
-register_element("Discontinuous Lagrange Trace", "DGT", 0, L2, "identity", (0, None), any_cell)
-register_element("Regge", "Regge",            2, HEin, "pullback as metric", (0, None), simplices[1:])
+register_element("Boundary Quadrature", "BQ", 0, L2, "identity", (0, None),
+                 any_cell)
+register_element("Bubble", "B", 0, H1, "identity", (2, None), simplices)
+register_element("Quadrature", "Quadrature", 0, L2, "identity", (0, None),
+                 any_cell)
+register_element("Real", "R", 0, L2, "identity", (0, 0),
+                 any_cell + ("TensorProductCell",))
+register_element("Undefined", "U", 0, L2, "identity", (0, None), any_cell)
+register_element("Radau", "Rad", 0, L2, "identity", (0, None), ("interval",))
+register_element("Regge", "Regge", 2, HEin, "double covariant Piola",
+                 (0, None), simplices[1:])
+register_element("HDiv Trace", "HDivT", 0, L2, "identity", (0, None), any_cell)
+register_element("Hellan-Herrmann-Johnson", "HHJ", 2, HDivDiv,
+                 "double contravariant Piola", (0, None), ("triangle",))
+# Spectral elements.
+register_element("Gauss-Legendre", "GL", 0, L2, "identity", (0, None),
+                 ("interval",))
+register_element("Gauss-Lobatto-Legendre", "GLL", 0, H1, "identity", (1, None),
+                 ("interval",))
+register_alias("Lobatto",
+               lambda family, dim, order, degree: ("Gauss-Lobatto-Legendre", order))
+register_alias("Lob",
+               lambda family, dim, order, degree: ("Gauss-Lobatto-Legendre", order))
+
 
 # Let Nedelec H(div) elements be aliases to BDMs/RTs
 register_alias("Nedelec 1st kind H(div)",
@@ -128,97 +171,133 @@ register_alias("N1div",
                lambda family, dim, order, degree: ("Raviart-Thomas", order))
 
 register_alias("Nedelec 2nd kind H(div)",
-               lambda family, dim, order, degree: ("Brezzi-Douglas-Marini", order))
+               lambda family, dim, order, degree: ("Brezzi-Douglas-Marini",
+                                                   order))
 register_alias("N2div",
-               lambda family, dim, order, degree: ("Brezzi-Douglas-Marini", order))
+               lambda family, dim, order, degree: ("Brezzi-Douglas-Marini",
+                                                   order))
+
+# Let Discontinuous Lagrange Trace element be alias to HDiv Trace
+register_alias("Discontinuous Lagrange Trace",
+               lambda family, dim, order, degree: ("HDiv Trace", order))
+register_alias("DGT",
+               lambda family, dim, order, degree: ("HDiv Trace", order))
 
 # New elements introduced for the periodic table 2014
-register_element2("Q",     0, H1,    "identity",            (1, None), cubes)
-register_element2("DQ",    0, L2,    "identity",            (0, None), cubes)
-register_element2("RTCE",  1, HCurl, "covariant Piola",     (1, None), ("quadrilateral",))
-register_element2("RTCF",  1, HDiv,  "contravariant Piola", (1, None), ("quadrilateral",))
-register_element2("NCE",   1, HCurl, "covariant Piola",     (1, None), ("hexahedron",))
-register_element2("NCF",   1, HDiv,  "contravariant Piola", (1, None), ("hexahedron",))
-
-register_element2("S",     0, H1,    "identity",            (1, None), cubes)
-register_element2("DPC",   0, L2,    "identity",            (1, None), cubes)
-register_element2("BDMCE", 1, HCurl, "covariant Piola",     (1, None), ("quadrilateral",))
-register_element2("BDMCF", 1, HDiv,  "contravariant Piola", (1, None), ("quadrilateral",))
-register_element2("AAE",   1, HCurl, "covariant Piola",     (1, None), ("hexahedron",))
-register_element2("AAF",   1, HDiv,  "contravariant Piola", (1, None), ("hexahedron",))
+register_element2("Q", 0, H1, "identity", (1, None), cubes)
+register_element2("DQ", 0, L2, "identity", (0, None), cubes)
+register_element2("RTCE", 1, HCurl, "covariant Piola", (1, None),
+                  ("quadrilateral",))
+register_element2("RTCF", 1, HDiv, "contravariant Piola", (1, None),
+                  ("quadrilateral",))
+register_element2("NCE", 1, HCurl, "covariant Piola", (1, None),
+                  ("hexahedron",))
+register_element2("NCF", 1, HDiv, "contravariant Piola", (1, None),
+                  ("hexahedron",))
+
+register_element2("S", 0, H1, "identity", (1, None), cubes)
+register_element2("DPC", 0, L2, "identity", (1, None), cubes)
+register_element2("BDMCE", 1, HCurl, "covariant Piola", (1, None),
+                  ("quadrilateral",))
+register_element2("BDMCF", 1, HDiv, "contravariant Piola", (1, None),
+                  ("quadrilateral",))
+register_element2("AAE", 1, HCurl, "covariant Piola", (1, None),
+                  ("hexahedron",))
+register_element2("AAF", 1, HDiv, "contravariant Piola", (1, None),
+                  ("hexahedron",))
 
 # New aliases introduced for the periodic table 2014
-register_alias("P",    lambda family, dim, order, degree: ("Lagrange",                 order))
-register_alias("DP",   lambda family, dim, order, degree: ("Discontinuous Lagrange",   order))
-register_alias("RTE",  lambda family, dim, order, degree: ("Nedelec 1st kind H(curl)", order))
-register_alias("RTF",  lambda family, dim, order, degree: ("Raviart-Thomas",           order))
-register_alias("N1E",  lambda family, dim, order, degree: ("Nedelec 1st kind H(curl)", order))
-register_alias("N1F",  lambda family, dim, order, degree: ("Raviart-Thomas",           order))
-
-register_alias("BDME", lambda family, dim, order, degree: ("Nedelec 2nd kind H(curl)", order))
-register_alias("BDMF", lambda family, dim, order, degree: ("Brezzi-Douglas-Marini",    order))
-register_alias("N2E",  lambda family, dim, order, degree: ("Nedelec 2nd kind H(curl)", order))
-register_alias("N2F",  lambda family, dim, order, degree: ("Brezzi-Douglas-Marini",    order))
-
-# Finite element exterior calculus notation
+register_alias("P", lambda family, dim, order, degree: ("Lagrange", order))
+register_alias("DP", lambda family, dim, order,
+               degree: ("Discontinuous Lagrange", order))
+register_alias("RTE", lambda family, dim, order,
+               degree: ("Nedelec 1st kind H(curl)", order))
+register_alias("RTF", lambda family, dim, order,
+               degree: ("Raviart-Thomas", order))
+register_alias("N1E", lambda family, dim, order,
+               degree: ("Nedelec 1st kind H(curl)", order))
+register_alias("N1F", lambda family, dim, order, degree: ("Raviart-Thomas",
+                                                          order))
+
+register_alias("BDME", lambda family, dim, order,
+               degree: ("Nedelec 2nd kind H(curl)", order))
+register_alias("BDMF", lambda family, dim, order,
+               degree: ("Brezzi-Douglas-Marini", order))
+register_alias("N2E", lambda family, dim, order,
+               degree: ("Nedelec 2nd kind H(curl)", order))
+register_alias("N2F", lambda family, dim, order,
+               degree: ("Brezzi-Douglas-Marini", order))
+
+
 def feec_element(family, n, r, k):
-    # n = topological dimension of domain
-    # r = polynomial order
-    # k = form_degree
+    """Finite element exterior calculus notation
+    n = topological dimension of domain
+    r = polynomial order
+    k = form_degree"""
 
-    # Note: We always map to edge elements in 2D, don't know how to differentiate otherwise?
+    # Note: We always map to edge elements in 2D, don't know how to
+    # differentiate otherwise?
 
-    # Mapping from (feec name, domain dimension, form degree) to (family name, polynomial order)
+    # Mapping from (feec name, domain dimension, form degree) to
+    # (family name, polynomial order)
     _feec_elements = {
         "P- Lambda": (
             (("P", r), ("DP", r - 1)),
-            (("P", r), ("RTE", r),      ("DP", r - 1)),
-            (("P", r), ("N1E", r),      ("N1F", r),   ("DP", r - 1)),
-            ),
+            (("P", r), ("RTE", r), ("DP", r - 1)),
+            (("P", r), ("N1E", r), ("N1F", r), ("DP", r - 1)),
+        ),
         "P Lambda": (
             (("P", r), ("DP", r)),
-            (("P", r), ("BDME", r),     ("DP", r)),
-            (("P", r), ("N2E", r),      ("N2F", r),   ("DP", r)),
-            ),
+            (("P", r), ("BDME", r), ("DP", r)),
+            (("P", r), ("N2E", r), ("N2F", r), ("DP", r)),
+        ),
         "Q- Lambda": (
             (("Q", r), ("DQ", r - 1)),
-            (("Q", r), ("RTCE", r),     ("DQ", r - 1)),
-            (("Q", r), ("NCE", r),      ("NCF", r),   ("DQ", r - 1)),
-            ),
+            (("Q", r), ("RTCE", r), ("DQ", r - 1)),
+            (("Q", r), ("NCE", r), ("NCF", r), ("DQ", r - 1)),
+        ),
         "S Lambda": (
             (("S", r), ("DPC", r)),
-            (("S", r), ("BDMCE", r),    ("DPC", r)),
-            (("S", r), ("AAE", r),      ("AAF", r),   ("DPC", r)),
-            ),
-        }
+            (("S", r), ("BDMCE", r), ("DPC", r)),
+            (("S", r), ("AAE", r), ("AAF", r), ("DPC", r)),
+        ),
+    }
 
-    # New notation, old verbose notation (including "Lambda") might be removed
+    # New notation, old verbose notation (including "Lambda") might be
+    # removed
     _feec_elements["P-"] = _feec_elements["P- Lambda"]
-    _feec_elements["P"]  = _feec_elements["P Lambda"]
+    _feec_elements["P"] = _feec_elements["P Lambda"]
     _feec_elements["Q-"] = _feec_elements["Q- Lambda"]
-    _feec_elements["S"]  = _feec_elements["S Lambda"]
+    _feec_elements["S"] = _feec_elements["S Lambda"]
 
     family, r = _feec_elements[family][n - 1][k]
 
     return family, r
 
+
 # General FEEC notation, old verbose (can be removed)
-register_alias("P- Lambda", lambda family, dim, order, degree: feec_element(family, dim, order, degree))
-register_alias("P Lambda",  lambda family, dim, order, degree: feec_element(family, dim, order, degree))
-register_alias("Q- Lambda", lambda family, dim, order, degree: feec_element(family, dim, order, degree))
-register_alias("S Lambda",  lambda family, dim, order, degree: feec_element(family, dim, order, degree))
+register_alias("P- Lambda", lambda family, dim, order,
+               degree: feec_element(family, dim, order, degree))
+register_alias("P Lambda", lambda family, dim, order,
+               degree: feec_element(family, dim, order, degree))
+register_alias("Q- Lambda", lambda family, dim, order,
+               degree: feec_element(family, dim, order, degree))
+register_alias("S Lambda", lambda family, dim, order,
+               degree: feec_element(family, dim, order, degree))
 
 # General FEEC notation, new compact notation
-register_alias("P-", lambda family, dim, order, degree: feec_element(family, dim, order, degree))
-#register_alias("P Lambda",  lambda family, dim, order, degree: feec_element(family, dim, order, degree))
-register_alias("Q-", lambda family, dim, order, degree: feec_element(family, dim, order, degree))
-#register_alias("S Lambda",  lambda family, dim, order, degree: feec_element(family, dim, order, degree))
+register_alias("P-", lambda family, dim, order,
+               degree: feec_element(family, dim, order, degree))
+register_alias("Q-", lambda family, dim, order,
+               degree: feec_element(family, dim, order, degree))
+
 
 def canonical_element_description(family, cell, order, form_degree):
     """Given basic element information, return corresponding element information on canonical form.
 
     Input: family, cell, (polynomial) order, form_degree
-    Output: family (canonical), short_name (for printing), order, value shape, reference value shape, sobolev_space
+    Output: family (canonical), short_name (for printing), order, value shape,
+    reference value shape, sobolev_space.
 
     This is used by the FiniteElement constructor to ved input
     data against the element list and aliases defined in ufl.
@@ -243,49 +322,57 @@ def canonical_element_description(family, cell, order, form_degree):
 
     # Check whether this family is an alias for something else
     while family in aliases:
-        ufl_assert(tdim is not None, "Need dimension to handle element aliases.")
+        if tdim is None:
+            error("Need dimension to handle element aliases.")
         (family, order) = aliases[family](family, tdim, order, form_degree)
-        #info_blue("%s, is an alias for %s " % (
-        #        (family, cell, order, form_degree),
-        #        (name, dummy_cell, r)))
 
     # Check that the element family exists
-    ufl_assert(family in ufl_elements,
-               'Unknown finite element "%s".' % family)
+    if family not in ufl_elements:
+        error('Unknown finite element "%s".' % family)
 
-    # Check that element data is valid (and also get common family name)
+    # Check that element data is valid (and also get common family
+    # name)
     (family, short_name, value_rank, sobolev_space, mapping, krange, cellnames) = ufl_elements[family]
 
+    # Accept CG/DG on all kind of cells, but use Q/DQ on "product" cells
+    if cellname in set(cubes) - set(simplices) or isinstance(cell, TensorProductCell):
+        if family == "Lagrange":
+            family = "Q"
+        elif family == "Discontinuous Lagrange":
+            if order >= 1:
+                warning("Discontinuous Lagrange element requested on %s, creating DQ element." % cell.cellname())
+            family = "DQ"
+
     # Validate cellname if a valid cell is specified
-    ufl_assert(cellname is None or cellname in cellnames,
-        'Cellname "%s" invalid for "%s" finite element.' % (cellname, family))
+    if not (cellname is None or cellname in cellnames):
+        error('Cellname "%s" invalid for "%s" finite element.' % (cellname, family))
 
     # Validate order if specified
     if order is not None:
-        ufl_assert(krange is not None,
-                   'Order "%s" invalid for "%s" finite element, '
-                       'should be None.' % (order, family))
+        if krange is None:
+            error('Order "%s" invalid for "%s" finite element, '
+                  'should be None.' % (order, family))
         kmin, kmax = krange
-        ufl_assert(kmin is None or order >= kmin,
-                   'Order "%s" invalid for "%s" finite element.' %
-                       (order, family))
-        ufl_assert(kmax is None or order <= kmax,
-               'Order "%s" invalid for "%s" finite element.' %
-                       (istr(order), family))
+        if not (kmin is None or order >= kmin):
+            error('Order "%s" invalid for "%s" finite element.' %
+                  (order, family))
+        if not (kmax is None or order <= kmax):
+            error('Order "%s" invalid for "%s" finite element.' %
+                  (istr(order), family))
 
     # Override sobolev_space for piecewise constants (TODO: necessary?)
     if order == 0:
         sobolev_space = L2
     if value_rank == 2:
         # Tensor valued fundamental elements in HEin have this shape
-        ufl_assert(gdim is not None and tdim is not None,
-               "Cannot infer shape of element without topological and geometric dimensions.")
+        if gdim is None or tdim is None:
+            error("Cannot infer shape of element without topological and geometric dimensions.")
         reference_value_shape = (tdim, tdim)
         value_shape = (gdim, gdim)
     elif value_rank == 1:
         # Vector valued fundamental elements in HDiv and HCurl have a shape
-        ufl_assert(gdim is not None and tdim is not None,
-               "Cannot infer shape of element without topological and geometric dimensions.")
+        if gdim is None or tdim is None:
+            error("Cannot infer shape of element without topological and geometric dimensions.")
         reference_value_shape = (tdim,)
         value_shape = (gdim,)
     elif value_rank == 0:
diff --git a/ufl/finiteelement/enrichedelement.py b/ufl/finiteelement/enrichedelement.py
index d4ddb46..6a581bf 100644
--- a/ufl/finiteelement/enrichedelement.py
+++ b/ufl/finiteelement/enrichedelement.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,56 +20,62 @@
 #
 # Modified by Kristian B. Oelgaard
 # Modified by Marie E. Rognes 2010, 2012
+# Modified by Massimiliano Leoni, 2016
 
+# import six
+from ufl.utils.py23 import as_native_str
 from six.moves import zip
-from ufl.assertions import ufl_assert
-from ufl.log import info_blue, warning, warning_blue, error
-
+from ufl.log import error
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
+
+# @six.python_2_unicode_compatible
 class EnrichedElement(FiniteElementBase):
     """The vector sum of two finite element spaces:
 
-        EnrichedElement(V, Q) = {v + q | v in V, q in Q}.
+        .. math:: \\textrm{EnrichedElement}(V, Q) = \\{v + q | v \\in V, q \\in Q\\}.
     """
     def __init__(self, *elements):
         self._elements = elements
 
         cell = elements[0].cell()
-        ufl_assert(all(e.cell() == cell for e in elements),
-                   "Cell mismatch for sub elements of enriched element.")
+        if not all(e.cell() == cell for e in elements[1:]):
+            error("Cell mismatch for sub elements of enriched element.")
 
         if isinstance(elements[0].degree(), int):
-            degrees = { e.degree() for e in elements } - { None }
+            degrees = {e.degree() for e in elements} - {None}
             degree = max(degrees) if degrees else None
         else:
             degree = tuple(map(max, zip(*[e.degree() for e in elements])))
 
-        # We can allow the scheme not to be defined, but all defined should be equal
+        # We can allow the scheme not to be defined, but all defined
+        # should be equal
         quad_schemes = [e.quadrature_scheme() for e in elements]
         quad_schemes = [qs for qs in quad_schemes if qs is not None]
         quad_scheme = quad_schemes[0] if quad_schemes else None
-        ufl_assert(all(qs == quad_scheme for qs in quad_schemes),
-            "Quadrature scheme mismatch.")
+        if not all(qs == quad_scheme for qs in quad_schemes):
+            error("Quadrature scheme mismatch.")
 
         value_shape = elements[0].value_shape()
-        ufl_assert(all(e.value_shape() == value_shape for e in elements),
-                   "Element value shape mismatch.")
+        if not all(e.value_shape() == value_shape for e in elements[1:]):
+            error("Element value shape mismatch.")
 
         reference_value_shape = elements[0].reference_value_shape()
-        ufl_assert(all(e.reference_value_shape() == reference_value_shape for e in elements),
-                   "Element reference value shape mismatch.")
+        if not all(e.reference_value_shape() == reference_value_shape for e in elements[1:]):
+            error("Element reference value shape mismatch.")
 
-        #mapping = elements[0].mapping() # FIXME: This fails for a mixed subelement here.
-        #ufl_assert(all(e.mapping() == mapping for e in elements),
-        #           "Element mapping mismatch.")
+        # mapping = elements[0].mapping() # FIXME: This fails for a mixed subelement here.
+        # if not all(e.mapping() == mapping for e in elements[1:]):
+        #    error("Element mapping mismatch.")
 
         # Initialize element data
         FiniteElementBase.__init__(self, "EnrichedElement", cell, degree,
-                                   quad_scheme, value_shape, reference_value_shape)
+                                   quad_scheme, value_shape,
+                                   reference_value_shape)
 
         # Cache repr string
-        self._repr = "EnrichedElement(%s)" % ", ".join(repr(e) for e in self._elements)
+        self._repr = as_native_str("EnrichedElement(%s)" %
+            ", ".join(repr(e) for e in self._elements))
 
     def is_cellwise_constant(self):
         """Return whether the basis functions of this
diff --git a/ufl/finiteelement/facetelement.py b/ufl/finiteelement/facetelement.py
index cfc9d5a..806917a 100644
--- a/ufl/finiteelement/facetelement.py
+++ b/ufl/finiteelement/facetelement.py
@@ -15,16 +15,21 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
+# import six
+from ufl.utils.py23 import as_native_str
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
 
+# @six.python_2_unicode_compatible
 class FacetElement(FiniteElementBase):
     """A version of an existing Finite Element space in which all dofs
-    associated with the interior have been discarded"""
+    associated with the interior have been discarded."""
     def __init__(self, element):
         self._element = element
-        self._repr = "FacetElement(%r)" % (element,)
+        self._repr = as_native_str("FacetElement(%s)" % repr(element))
 
         family = "FacetElement"
         cell = element.cell()
@@ -42,7 +47,5 @@ class FacetElement(FiniteElementBase):
         return "FacetElement(%s)" % str(self._element)
 
     def shortstr(self):
+        "Format as string for pretty printing."
         return "FacetElement(%s)" % str(self._element.shortstr())
-
-    def __repr__(self):
-        return self._repr
diff --git a/ufl/finiteelement/finiteelement.py b/ufl/finiteelement/finiteelement.py
index 8dfccee..e04c54a 100644
--- a/ufl/finiteelement/finiteelement.py
+++ b/ufl/finiteelement/finiteelement.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,22 +21,113 @@
 # Modified by Kristian B. Oelgaard
 # Modified by Marie E. Rognes 2010, 2012
 # Modified by Anders Logg 2014
+# Modified by Massimiliano Leoni, 2016
 
-from ufl.assertions import ufl_assert
+# import six
+from ufl.log import error
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 from ufl.utils.formatting import istr
 from ufl.cell import as_cell
-from ufl.log import info_blue, warning, warning_blue, error
 
-from ufl.finiteelement.elementlist import canonical_element_description
+from ufl.cell import TensorProductCell
+from ufl.finiteelement.elementlist import canonical_element_description, simplices
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
+
+# @six.python_2_unicode_compatible
 class FiniteElement(FiniteElementBase):
-    "The basic finite element class for all simple finite elements"
+    "The basic finite element class for all simple finite elements."
     # TODO: Move these to base?
-    __slots__ = ("_short_name",
-                 "_sobolev_space",
-                 "_mapping",
-                )
+    __slots__ = as_native_strings((
+        "_short_name",
+        "_sobolev_space",
+        "_mapping",
+        ))
+
+    def __new__(cls,
+                family,
+                cell=None,
+                degree=None,
+                form_degree=None,
+                quad_scheme=None):
+        """Intercepts construction to expand CG, DG, RTCE and RTCF
+        spaces on TensorProductCells."""
+        if cell is not None:
+            cell = as_cell(cell)
+
+        if isinstance(cell, TensorProductCell):
+            family, short_name, degree, value_shape, reference_value_shape, sobolev_space, mapping = \
+                canonical_element_description(family, cell, degree, form_degree)
+
+            # Delay import to avoid circular dependency at module load time
+            from ufl.finiteelement.tensorproductelement import TensorProductElement
+            from ufl.finiteelement.enrichedelement import EnrichedElement
+            from ufl.finiteelement.hdivcurl import HDivElement as HDiv, HCurlElement as HCurl
+
+            if family in ["RTCF", "RTCE"]:
+                if cell._cells[0].cellname() != "interval":
+                    error("%s is available on TensorProductCell(interval, interval) only." % family)
+                if cell._cells[1].cellname() != "interval":
+                    error("%s is available on TensorProductCell(interval, interval) only." % family)
+
+                C_elt = FiniteElement("CG", "interval", degree, 0, quad_scheme)
+                D_elt = FiniteElement("DG", "interval", degree - 1, 1, quad_scheme)
+
+                CxD_elt = TensorProductElement(C_elt, D_elt, cell=cell)
+                DxC_elt = TensorProductElement(D_elt, C_elt, cell=cell)
+
+                if family == "RTCF":
+                    return EnrichedElement(HDiv(CxD_elt), HDiv(DxC_elt))
+                if family == "RTCE":
+                    return EnrichedElement(HCurl(CxD_elt), HCurl(DxC_elt))
+
+            elif family == "NCF":
+                if cell._cells[0].cellname() != "quadrilateral":
+                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)
+                if cell._cells[1].cellname() != "interval":
+                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)
+
+                Qc_elt = FiniteElement("RTCF", "quadrilateral", degree, 1, quad_scheme)
+                Qd_elt = FiniteElement("DQ", "quadrilateral", degree - 1, 2, quad_scheme)
+
+                Id_elt = FiniteElement("DG", "interval", degree - 1, 1, quad_scheme)
+                Ic_elt = FiniteElement("CG", "interval", degree, 0, quad_scheme)
+
+                return EnrichedElement(HDiv(TensorProductElement(Qc_elt, Id_elt, cell=cell)),
+                                       HDiv(TensorProductElement(Qd_elt, Ic_elt, cell=cell)))
+
+            elif family == "NCE":
+                if cell._cells[0].cellname() != "quadrilateral":
+                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)
+                if cell._cells[1].cellname() != "interval":
+                    error("%s is available on TensorProductCell(quadrilateral, interval) only." % family)
+
+                Qc_elt = FiniteElement("Q", "quadrilateral", degree, 0, quad_scheme)
+                Qd_elt = FiniteElement("RTCE", "quadrilateral", degree, 1, quad_scheme)
+
+                Id_elt = FiniteElement("DG", "interval", degree - 1, 1, quad_scheme)
+                Ic_elt = FiniteElement("CG", "interval", degree, 0, quad_scheme)
+
+                return EnrichedElement(HCurl(TensorProductElement(Qc_elt, Id_elt, cell=cell)),
+                                       HCurl(TensorProductElement(Qd_elt, Ic_elt, cell=cell)))
+
+            elif family == "Q":
+                return TensorProductElement(FiniteElement("CG", cell._cells[0], degree, 0, quad_scheme),
+                                            FiniteElement("CG", cell._cells[1], degree, 0, quad_scheme),
+                                            cell=cell)
+
+            elif family == "DQ":
+                family_A = "DG" if cell._cells[0].cellname() in simplices else "DQ"
+                family_B = "DG" if cell._cells[1].cellname() in simplices else "DQ"
+                elem_A = FiniteElement(family_A, cell._cells[0], degree,
+                                       cell._cells[0].topological_dimension(), quad_scheme)
+                elem_B = FiniteElement(family_B, cell._cells[1], degree,
+                                       cell._cells[1].topological_dimension(), quad_scheme)
+                return TensorProductElement(elem_A, elem_B, cell=cell)
+
+        return super(FiniteElement, cls).__new__(cls)
+
     def __init__(self,
                  family,
                  cell=None,
@@ -58,32 +149,44 @@ class FiniteElement(FiniteElementBase):
             quad_scheme
                The quadrature scheme (optional)
         """
-        # Note: Unfortunately, dolfin sometimes passes None for cell. Until this is fixed, allow it:
+        # Note: Unfortunately, dolfin sometimes passes None for
+        # cell. Until this is fixed, allow it:
         if cell is not None:
             cell = as_cell(cell)
 
-        family, short_name, degree, value_shape, reference_value_shape, sobolev_space, mapping = \
-          canonical_element_description(family, cell, degree, form_degree)
+        family, short_name, degree, value_shape, reference_value_shape, sobolev_space, mapping = canonical_element_description(family, cell, degree, form_degree)
 
-        # TODO: Move these to base? Might be better to instead simplify base though.
+        # TODO: Move these to base? Might be better to instead
+        # simplify base though.
         self._sobolev_space = sobolev_space
         self._mapping = mapping
         self._short_name = short_name
 
+        # Finite elements on quadrilaterals have an IrreducibleInt as degree
+        if cell is not None:
+            if cell.cellname() == "quadrilateral":
+                from ufl.algorithms.estimate_degrees import IrreducibleInt
+                degree = IrreducibleInt(degree)
+
         # Initialize element data
-        FiniteElementBase.__init__(self, family, cell, degree,
-                                   quad_scheme, value_shape, reference_value_shape)
+        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
+                                   value_shape, reference_value_shape)
 
         # Cache repr string
         qs = self.quadrature_scheme()
-        quad_str = "" if qs is None else ", quad_scheme=%r" % (qs,)
-        self._repr = "FiniteElement(%r, %r, %r%s)" % (self.family(), self.cell(), self.degree(), quad_str)
+        if qs is None:
+            quad_str = ""
+        else:
+            quad_str = ", quad_scheme=%s" % repr(qs)
+        self._repr = as_native_str("FiniteElement(%s, %s, %s%s)" % (
+            repr(self.family()), repr(self.cell()), repr(self.degree()), quad_str))
         assert '"' not in self._repr
 
     def mapping(self):
         return self._mapping
 
     def sobolev_space(self):
+        "Return the underlying Sobolev space."
         return self._sobolev_space
 
     def __str__(self):
@@ -91,9 +194,17 @@ class FiniteElement(FiniteElementBase):
         qs = self.quadrature_scheme()
         qs = "" if qs is None else "(%s)" % qs
         return "<%s%s%s on a %s>" % (self._short_name, istr(self.degree()),
-                                           qs, self.cell())
+                                     qs, self.cell())
 
     def shortstr(self):
         "Format as string for pretty printing."
         return "%s%s(%s)" % (self._short_name, istr(self.degree()),
                              istr(self.quadrature_scheme()))
+
+    def __getnewargs__(self):
+        """Return the arguments which pickle needs to recreate the object."""
+        return (self.family(),
+                self.cell(),
+                self.degree(),
+                None,
+                self.quadrature_scheme())
diff --git a/ufl/finiteelement/finiteelementbase.py b/ufl/finiteelement/finiteelementbase.py
index c8f9294..1e30297 100644
--- a/ufl/finiteelement/finiteelementbase.py
+++ b/ufl/finiteelement/finiteelementbase.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,38 +20,50 @@
 #
 # Modified by Kristian B. Oelgaard
 # Modified by Marie E. Rognes 2010, 2012
+# Modified by Massimiliano Leoni, 2016
 
 from six.moves import zip
-from ufl.assertions import ufl_assert
-from ufl.permutation import compute_indices
+from six import string_types
+
+from ufl.utils.py23 import as_native_strings
 from ufl.utils.sequences import product
-from ufl.utils.formatting import istr
 from ufl.utils.dicts import EmptyDict
-from ufl.log import info_blue, warning, warning_blue, error
+from ufl.log import error
 from ufl.cell import AbstractCell, as_cell
 
+
 class FiniteElementBase(object):
-    "Base class for all finite elements"
-    __slots__ = ("_family",
-                 "_cell",
-                 "_degree",
-                 "_form_degree",
-                 "_quad_scheme",
-                 "_value_shape",
-                 "_reference_value_shape",
-                 "_repr",
-                 "__weakref__")
-    # TODO: Not all these should be in the base class! In particular family, degree, and quad_scheme do not belong here.
-    def __init__(self, family, cell, degree, quad_scheme, value_shape, reference_value_shape):
-        "Initialize basic finite element data"
-        ufl_assert(isinstance(family, str), "Invalid family type.")
-        ufl_assert(isinstance(degree, (int, tuple)) or degree is None, "Invalid degree type.")
-        ufl_assert(isinstance(value_shape, tuple), "Invalid value_shape type.")
-        ufl_assert(isinstance(reference_value_shape, tuple), "Invalid reference_value_shape type.")
+    "Base class for all finite elements."
+    __slots__ = as_native_strings((
+        "_family",
+        "_cell",
+        "_degree",
+        "_form_degree",
+        "_quad_scheme",
+        "_value_shape",
+        "_reference_value_shape",
+        "_repr",
+        "__weakref__",
+        ))
+
+    # TODO: Not all these should be in the base class! In particular
+    # family, degree, and quad_scheme do not belong here.
+    def __init__(self, family, cell, degree, quad_scheme, value_shape,
+                 reference_value_shape):
+        "Initialize basic finite element data."
+        if not isinstance(family, string_types):
+            error("Invalid family type.")
+        if not (degree is None or isinstance(degree, (int, tuple))):
+            error("Invalid degree type.")
+        if not isinstance(value_shape, tuple):
+            error("Invalid value_shape type.")
+        if not isinstance(reference_value_shape, tuple):
+            error("Invalid reference_value_shape type.")
 
         if cell is not None:
             cell = as_cell(cell)
-            ufl_assert(isinstance(cell, AbstractCell), "Invalid cell type.")
+            if not isinstance(cell, AbstractCell):
+                error("Invalid cell type.")
 
         self._family = family
         self._cell = cell
@@ -60,14 +72,23 @@ class FiniteElementBase(object):
         self._reference_value_shape = reference_value_shape
         self._quad_scheme = quad_scheme
 
-
     def __repr__(self):
-        "Format as string for evaluation as Python object."
+        """Format as string for evaluation as Python object.
+
+        NB! Assumes subclass has assigned its repr string to self._repr.
+        """
         return self._repr
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def _ufl_hash_data_(self):
         return repr(self)
 
+    def _ufl_signature_data_(self):
+        return repr(self)
+
     def __hash__(self):
         "Compute hash code for insertion in hashmaps."
         return hash(self._ufl_hash_data_())
@@ -76,29 +97,34 @@ class FiniteElementBase(object):
         "Compute element equality for insertion in hashmaps."
         return type(self) == type(other) and self._ufl_hash_data_() == other._ufl_hash_data_()
 
+    def __ne__(self, other):
+        "Compute element inequality for insertion in hashmaps."
+        return not self.__eq__(other)
+
     def __lt__(self, other):
         "Compare elements by repr, to give a natural stable sorting."
         return repr(self) < repr(other)
 
-
-    def family(self): # FIXME: Undefined for base?
-        "Return finite element family"
+    def family(self):  # FIXME: Undefined for base?
+        "Return finite element family."
         return self._family
 
     def degree(self, component=None):
-        "Return polynomial degree of finite element"
-        # FIXME: Consider embedded_degree concept for more accurate degree, see blueprint
+        "Return polynomial degree of finite element."
+        # FIXME: Consider embedded_degree concept for more accurate
+        # degree, see blueprint
         return self._degree
 
     def quadrature_scheme(self):
-        "Return quadrature scheme of finite element"
+        "Return quadrature scheme of finite element."
         return self._quad_scheme
 
     def mapping(self):
+        "Not implemented."
         error("Missing implementation of mapping().")
 
     def cell(self):
-        "Return cell of finite element"
+        "Return cell of finite element."
         return self._cell
 
     def is_cellwise_constant(self, component=None):
@@ -122,9 +148,11 @@ class FiniteElementBase(object):
         "Return the integer product of the reference value shape."
         return product(self.reference_value_shape())
 
-    def symmetry(self): # FIXME: different approach
-        """Return the symmetry dict, which is a mapping c0 -> c1
-        meaning that component c0 is represented by component c1."""
+    def symmetry(self):  # FIXME: different approach
+        """Return the symmetry dict, which is a mapping :math:`c_0 \\to c_1`
+        meaning that component :math:`c_0` is represented by component
+        :math:`c_1`.
+        A component is a tuple of one or more ints."""
         return EmptyDict
 
     def _check_component(self, i):
@@ -132,12 +160,12 @@ class FiniteElementBase(object):
         sh = self.value_shape()
         r = len(sh)
         if not (len(i) == r and all(j < k for (j, k) in zip(i, sh))):
-            error(("Illegal component index '%r' (value rank %d)" +
+            error(("Illegal component index '%s' (value rank %d)" +
                    "for element (value rank %d).") % (i, len(i), r))
 
     def extract_subelement_component(self, i):
         """Extract direct subelement index and subelement relative
-        component index for a given component index"""
+        component index for a given component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_component(i)
@@ -145,23 +173,23 @@ class FiniteElementBase(object):
 
     def extract_component(self, i):
         """Recursively extract component index relative to a (simple) element
-        and that element for given value component index"""
+        and that element for given value component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_component(i)
         return (i, self)
 
     def _check_reference_component(self, i):
-        "Check that reference component index i is valid"
+        "Check that reference component index i is valid."
         sh = self.value_shape()
         r = len(sh)
         if not (len(i) == r and all(j < k for (j, k) in zip(i, sh))):
-            error(("Illegal component index '%r' (value rank %d)" +
+            error(("Illegal component index '%s' (value rank %d)" +
                    "for element (value rank %d).") % (i, len(i), r))
 
     def extract_subelement_reference_component(self, i):
         """Extract direct subelement index and subelement relative
-        reference component index for a given reference component index"""
+        reference component index for a given reference component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_reference_component(i)
@@ -169,33 +197,31 @@ class FiniteElementBase(object):
 
     def extract_reference_component(self, i):
         """Recursively extract reference component index relative to a (simple) element
-        and that element for given reference value component index"""
+        and that element for given reference value component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_reference_component(i)
         return (i, self)
 
     def num_sub_elements(self):
-        "Return number of sub elements"
+        "Return number of sub-elements."
         return 0
 
     def sub_elements(self):
-        "Return list of sub elements"
+        "Return list of sub-elements."
         return []
 
     def __add__(self, other):
         "Add two elements, creating an enriched element"
-        ufl_assert(isinstance(other, FiniteElementBase),
-                   "Can't add element and %s." % other.__class__)
-        warning_blue("WARNING: Creating an EnrichedElement,\n         " +
-                     "if you intended to create a MixedElement use '*' instead of '+'.")
+        if not isinstance(other, FiniteElementBase):
+            error("Can't add element and %s." % other.__class__)
         from ufl.finiteelement import EnrichedElement
         return EnrichedElement(self, other)
 
     def __mul__(self, other):
         "Multiply two elements, creating a mixed element"
-        ufl_assert(isinstance(other, FiniteElementBase),
-                   "Can't multiply element and %s." % other.__class__)
+        if not isinstance(other, FiniteElementBase):
+            error("Can't multiply element and %s." % other.__class__)
         from ufl.finiteelement import MixedElement
         return MixedElement(self, other)
 
diff --git a/ufl/finiteelement/hdivcurl.py b/ufl/finiteelement/hdivcurl.py
index a6c50cb..431e4b1 100644
--- a/ufl/finiteelement/hdivcurl.py
+++ b/ufl/finiteelement/hdivcurl.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright (C) 2008-2015 Andrew T. T. McRae
+# Copyright (C) 2008-2016 Andrew T. T. McRae
 #
 # This file is part of UFL.
 #
@@ -15,68 +15,75 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
-from ufl.finiteelement.outerproductelement import OuterProductElement
+# import six
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
 
-class HDivElement(OuterProductElement):
+# @six.python_2_unicode_compatible
+class HDivElement(FiniteElementBase):
     """A div-conforming version of an outer product element, assuming
     this makes mathematical sense."""
-    __slots__ = ("_element")
+    __slots__ = as_native_strings(("_element",))
 
     def __init__(self, element):
         self._element = element
-        self._repr = "HDivElement(%r)" % (element,)
-        self._mapping = "contravariant Piola"
+        self._repr = as_native_str("HDivElement(%s)" % repr(element))
 
-        family = "OuterProductElement"
+        family = "TensorProductElement"
         cell = element.cell()
         degree = element.degree()
         quad_scheme = element.quadrature_scheme()
         value_shape = (element.cell().geometric_dimension(),)
         reference_value_shape = (element.cell().topological_dimension(),)
 
-        # Skipping OuterProductElement constructor! Bad code smell, refactor to avoid this non-inheritance somehow.
+        # Skipping TensorProductElement constructor! Bad code smell, refactor to avoid this non-inheritance somehow.
         FiniteElementBase.__init__(self, family, cell, degree,
                                    quad_scheme, value_shape, reference_value_shape)
 
+    def mapping(self):
+        return "contravariant Piola"
+
     def __str__(self):
         return "HDivElement(%s)" % str(self._element)
 
     def shortstr(self):
+        "Format as string for pretty printing."
         return "HDivElement(%s)" % str(self._element.shortstr())
 
-    def __repr__(self):
-        return self._repr
-
 
-class HCurlElement(OuterProductElement):
+# @six.python_2_unicode_compatible
+class HCurlElement(FiniteElementBase):
     """A curl-conforming version of an outer product element, assuming
     this makes mathematical sense."""
-    __slots__ = ("_element")
+    __slots__ = as_native_strings(("_element",))
 
     def __init__(self, element):
         self._element = element
-        self._repr = "HCurlElement(%r)" % (element,)
-        self._mapping = "covariant Piola"
+        self._repr = as_native_str("HCurlElement(%s)" % repr(element))
 
-        family = "OuterProductElement"
+        family = "TensorProductElement"
         cell = element.cell()
         degree = element.degree()
         quad_scheme = element.quadrature_scheme()
         cell = element.cell()
         value_shape = (cell.geometric_dimension(),)
-        reference_value_shape = (cell.topological_dimension(),) # TODO: Is this right?
-        # Skipping OuterProductElement constructor! Bad code smell, refactor to avoid this non-inheritance somehow.
-        FiniteElementBase.__init__(self, family, cell, degree,
-                                    quad_scheme, value_shape, reference_value_shape)
+        reference_value_shape = (cell.topological_dimension(),)  # TODO: Is this right?
+        # Skipping TensorProductElement constructor! Bad code smell,
+        # refactor to avoid this non-inheritance somehow.
+        FiniteElementBase.__init__(self, family, cell, degree, quad_scheme,
+                                   value_shape, reference_value_shape)
+
+    def mapping(self):
+        return "covariant Piola"
 
     def __str__(self):
         return "HCurlElement(%s)" % str(self._element)
 
     def shortstr(self):
+        "Format as string for pretty printing."
         return "HCurlElement(%s)" % str(self._element.shortstr())
-
-    def __repr__(self):
-        return self._repr
diff --git a/ufl/finiteelement/interiorelement.py b/ufl/finiteelement/interiorelement.py
index bcc0d57..30092bd 100644
--- a/ufl/finiteelement/interiorelement.py
+++ b/ufl/finiteelement/interiorelement.py
@@ -15,16 +15,21 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
+# import six
+from ufl.utils.py23 import as_native_str
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
 
+# @six.python_2_unicode_compatible
 class InteriorElement(FiniteElementBase):
     """A version of an existing Finite Element space in which only the dofs
-    associated with the interior have been kept"""
+    associated with the interior have been kept."""
     def __init__(self, element):
         self._element = element
-        self._repr = "InteriorElement(%r)" % (element,)
+        self._repr = as_native_str("InteriorElement(%s)" % repr(element))
 
         family = "InteriorElement"
         cell = element.cell()
@@ -42,7 +47,5 @@ class InteriorElement(FiniteElementBase):
         return "InteriorElement(%s)" % str(self._element)
 
     def shortstr(self):
+        "Format as string for pretty printing."
         return "InteriorElement(%s)" % str(self._element.shortstr())
-
-    def __repr__(self):
-        return self._repr
diff --git a/ufl/finiteelement/mixedelement.py b/ufl/finiteelement/mixedelement.py
index edba470..d706684 100644
--- a/ufl/finiteelement/mixedelement.py
+++ b/ufl/finiteelement/mixedelement.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,35 +21,37 @@
 # Modified by Kristian B. Oelgaard
 # Modified by Marie E. Rognes 2010, 2012
 # Modified by Anders Logg 2014
+# Modified by Massimiliano Leoni, 2016
 
-from itertools import chain
-
+# import six
 from six import iteritems
 from six.moves import zip
 from six.moves import xrange as range
 
-from ufl.assertions import ufl_assert
+from ufl.log import error
+from ufl.utils.py23 import as_native_strings
 from ufl.permutation import compute_indices
 from ufl.utils.sequences import product
-from ufl.utils.formatting import istr
 from ufl.utils.dicts import EmptyDict
 from ufl.utils.indexflattening import flatten_multiindex, unflatten_index, shape_to_strides
 from ufl.cell import as_cell
-from ufl.log import info_blue, warning, warning_blue, error
 
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 from ufl.finiteelement.finiteelement import FiniteElement
 
 
+# @six.python_2_unicode_compatible
 class MixedElement(FiniteElementBase):
-    "A finite element composed of a nested hierarchy of mixed or simple elements"
-    __slots__ = ("_sub_elements", "_cells")
+    """A finite element composed of a nested hierarchy of mixed or simple
+    elements."""
+    __slots__ = as_native_strings(("_sub_elements", "_cells"))
 
     def __init__(self, *elements, **kwargs):
         "Create mixed finite element from given list of elements"
 
         if type(self) is MixedElement:
-            ufl_assert(not kwargs, "Not expecting keyword arguments to MixedElement constructor.")
+            if kwargs:
+                error("Not expecting keyword arguments to MixedElement constructor.")
 
         # Un-nest arguments if we get a single argument with a list of elements
         if len(elements) == 1 and isinstance(elements[0], (tuple, list)):
@@ -65,57 +67,59 @@ class MixedElement(FiniteElementBase):
         if cells:
             cell = cells[0]
             # Require that all elements are defined on the same cell
-            ufl_assert(all(c == cell for c in cells[1:]),
-                       "Sub elements must live on the same cell.")
+            if not all(c == cell for c in cells[1:]):
+                error("Sub elements must live on the same cell.")
         else:
             cell = None
 
-        # Check that all elements use the same quadrature scheme
-        # TODO: We can allow the scheme not to be defined.
+        # Check that all elements use the same quadrature scheme TODO:
+        # We can allow the scheme not to be defined.
         quad_scheme = elements[0].quadrature_scheme()
-        ufl_assert(all(e.quadrature_scheme() == quad_scheme for e in elements),
-            "Quadrature scheme mismatch for sub elements of mixed element.")
+        if not all(e.quadrature_scheme() == quad_scheme for e in elements):
+            error("Quadrature scheme mismatch for sub elements of mixed element.")
 
         # Compute value sizes in global and reference configurations
         value_size_sum = sum(product(s.value_shape()) for s in self._sub_elements)
         reference_value_size_sum = sum(product(s.reference_value_shape()) for s in self._sub_elements)
 
-        # Default value shape: Treated simply as all subelement values unpacked in a vector.
+        # Default value shape: Treated simply as all subelement values
+        # unpacked in a vector.
         value_shape = kwargs.get('value_shape', (value_size_sum,))
 
-        # Default reference value shape: Treated simply as all subelement reference values unpacked in a vector.
+        # Default reference value shape: Treated simply as all
+        # subelement reference values unpacked in a vector.
         reference_value_shape = kwargs.get('reference_value_shape', (reference_value_size_sum,))
 
-        # Validate value_shape (deliberately not for subclasses VectorElement and TensorElement)
+        # Validate value_shape (deliberately not for subclasses
+        # VectorElement and TensorElement)
         if type(self) is MixedElement:
             # This is not valid for tensor elements with symmetries,
             # assume subclasses deal with their own validation
-            ufl_assert(product(value_shape) == value_size_sum,
-                "Provided value_shape doesn't match the total "
-                "value size of all subelements.")
+            if product(value_shape) != value_size_sum:
+                error("Provided value_shape doesn't match the "
+                      "total value size of all subelements.")
 
         # Initialize element data
-        degrees = { e.degree() for e in self._sub_elements } - { None }
+        degrees = {e.degree() for e in self._sub_elements} - {None}
         degree = max(degrees) if degrees else None
         FiniteElementBase.__init__(self, "Mixed", cell, degree, quad_scheme,
                                    value_shape, reference_value_shape)
 
         # Cache repr string
         if type(self) is MixedElement:
-            self._repr = "MixedElement(%s)" % ", ".join(repr(e) for e in self._sub_elements)
+            self._repr = "MixedElement(%s)" % (
+                ", ".join(repr(e) for e in self._sub_elements),)
 
     def reconstruct_from_elements(self, *elements):
         "Reconstruct a mixed element from new subelements."
         if all(a == b for (a, b) in zip(elements, self._sub_elements)):
             return self
-        ufl_assert(all(a.value_shape() == b.value_shape()
-                       for (a, b) in zip(elements, self._sub_elements)),
-            "Expecting new elements to have same value shape as old ones.")
         return MixedElement(*elements)
 
     def symmetry(self):
-        """Return the symmetry dict, which is a mapping c0 -> c1
-        meaning that component c0 is represented by component c1.
+        """Return the symmetry dict, which is a mapping :math:`c_0 \\to c_1`
+        meaning that component :math:`c_0` is represented by component
+        :math:`c_1`.
         A component is a tuple of one or more ints."""
         # Build symmetry map from symmetries of subelements
         sm = {}
@@ -124,15 +128,16 @@ class MixedElement(FiniteElementBase):
         for e in self._sub_elements:
             sh = e.value_shape()
             st = shape_to_strides(sh)
-            # Map symmetries of subelement into index space of this element
+            # Map symmetries of subelement into index space of this
+            # element
             for c0, c1 in iteritems(e.symmetry()):
                 j0 = flatten_multiindex(c0, st) + j
                 j1 = flatten_multiindex(c1, st) + j
                 sm[(j0,)] = (j1,)
             # Update base index for next element
             j += product(sh)
-        ufl_assert(j == product(self.value_shape()),
-                   "Size mismatch in symmetry algorithm.")
+        if j != product(self.value_shape()):
+            error("Size mismatch in symmetry algorithm.")
         return sm or EmptyDict
 
     def mapping(self):
@@ -151,14 +156,15 @@ class MixedElement(FiniteElementBase):
 
     def extract_subelement_component(self, i):
         """Extract direct subelement index and subelement relative
-        component index for a given component index"""
+        component index for a given component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_component(i)
 
         # Select between indexing modes
         if len(self.value_shape()) == 1:
-            # Indexing into a long vector of flattened subelement shapes
+            # Indexing into a long vector of flattened subelement
+            # shapes
             j, = i
 
             # Find subelement for this index
@@ -168,29 +174,30 @@ class MixedElement(FiniteElementBase):
                 if j < si:
                     break
                 j -= si
-            ufl_assert(j >= 0, "Moved past last value component!")
+            if j < 0:
+                error("Moved past last value component!")
 
             # Convert index into a shape tuple
             st = shape_to_strides(sh)
             component = unflatten_index(j, st)
         else:
-            # Indexing into a multidimensional tensor
-            # where subelement index is first axis
+            # Indexing into a multidimensional tensor where subelement
+            # index is first axis
             sub_element_index = i[0]
-            ufl_assert(sub_element_index < len(self._sub_elements),
-                       "Illegal component index (dimension %d)." % sub_element_index)
+            if sub_element_index >= len(self._sub_elements):
+                error("Illegal component index (dimension %d)." % sub_element_index)
             component = i[1:]
         return (sub_element_index, component)
 
     def extract_component(self, i):
         """Recursively extract component index relative to a (simple) element
-        and that element for given value component index"""
+        and that element for given value component index."""
         sub_element_index, component = self.extract_subelement_component(i)
         return self._sub_elements[sub_element_index].extract_component(component)
 
     def extract_subelement_reference_component(self, i):
         """Extract direct subelement index and subelement relative
-        reference_component index for a given reference_component index"""
+        reference_component index for a given reference_component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_reference_component(i)
@@ -207,7 +214,8 @@ class MixedElement(FiniteElementBase):
             if j < si:
                 break
             j -= si
-        ufl_assert(j >= 0, "Moved past last value reference_component!")
+        if j < 0:
+            error("Moved past last value reference_component!")
 
         # Convert index into a shape tuple
         st = shape_to_strides(sh)
@@ -216,7 +224,7 @@ class MixedElement(FiniteElementBase):
 
     def extract_reference_component(self, i):
         """Recursively extract reference_component index relative to a (simple) element
-        and that element for given value reference_component index"""
+        and that element for given value reference_component index."""
         sub_element_index, reference_component = self.extract_subelement_reference_component(i)
         return self._sub_elements[sub_element_index].extract_reference_component(reference_component)
 
@@ -230,9 +238,9 @@ class MixedElement(FiniteElementBase):
             return e.is_cellwise_constant()
 
     def degree(self, component=None):
-        "Return polynomial degree of finite element"
+        "Return polynomial degree of finite element."
         if component is None:
-            return self._degree # from FiniteElementBase, computed as max of subelements in __init__
+            return self._degree  # from FiniteElementBase, computed as max of subelements in __init__
         else:
             i, e = self.extract_component(component)
             return e.degree()
@@ -248,8 +256,9 @@ class MixedElement(FiniteElementBase):
         return "Mixed<" + tmp + ">"
 
 
+# @six.python_2_unicode_compatible
 class VectorElement(MixedElement):
-    "A special case of a mixed finite element where all elements are equal"
+    "A special case of a mixed finite element where all elements are equal."
 
     def __init__(self, family, cell=None, degree=None, dim=None,
                  form_degree=None, quad_scheme=None):
@@ -285,8 +294,8 @@ class VectorElement(MixedElement):
 
         # Set default size if not specified
         if dim is None:
-            ufl_assert(cell is not None,
-                       "Cannot infer vector dimension without a cell.")
+            if cell is None:
+                error("Cannot infer vector dimension without a cell.")
             dim = cell.geometric_dimension()
 
         # Create list of sub elements for mixed element constructor
@@ -297,31 +306,37 @@ class VectorElement(MixedElement):
         reference_value_shape = (dim,) + sub_element.reference_value_shape()
 
         # Initialize element data
-        MixedElement.__init__(self, sub_elements, value_shape=value_shape, reference_value_shape=reference_value_shape)
-        # FIXME: Storing this here is strange, isn't that handled by subclass?
+        MixedElement.__init__(self, sub_elements, value_shape=value_shape,
+                              reference_value_shape=reference_value_shape)
+        # FIXME: Storing this here is strange, isn't that handled by
+        # subclass?
         self._family = sub_element.family()
         self._degree = sub_element.degree()
         self._sub_element = sub_element
-        self._form_degree = form_degree # Storing for signature_data, not sure if it's needed
+        self._form_degree = form_degree  # Storing for signature_data, not sure if it's needed
 
         # Cache repr string
-        self._repr = "VectorElement(%r, dim=%d)" % (sub_element, len(self._sub_elements))
+        self._repr = "VectorElement(%s, dim=%d)" % (
+            repr(sub_element), len(self._sub_elements))
 
     def __str__(self):
         "Format as string for pretty printing."
         return ("<vector element with %d components of %s>" %
-               (len(self._sub_elements), self._sub_element))
+                (len(self._sub_elements), self._sub_element))
 
     def shortstr(self):
         "Format as string for pretty printing."
         return "Vector<%d x %s>" % (len(self._sub_elements),
                                     self._sub_element.shortstr())
 
+
+# @six.python_2_unicode_compatible
 class TensorElement(MixedElement):
-    "A special case of a mixed finite element where all elements are equal"
-    __slots__ = ("_sub_element", "_shape", "_symmetry",
+    "A special case of a mixed finite element where all elements are equal."
+    __slots__ = as_native_strings(("_sub_element", "_shape", "_symmetry",
                  "_sub_element_mapping", "_flattened_sub_element_mapping",
-                 "_mapping")
+                 "_mapping"))
+
     def __init__(self, family, cell=None, degree=None, shape=None,
                  symmetry=None, quad_scheme=None):
         """Create tensor element (repeated mixed element with optional symmetries).
@@ -344,13 +359,13 @@ class TensorElement(MixedElement):
             # Create scalar sub element
             sub_element = FiniteElement(family, cell, degree, quad_scheme)
 
-        ufl_assert(sub_element.value_shape() == (),
-                   "Expecting only scalar valued subelement for TensorElement.")
+        if sub_element.value_shape() != ():
+            error("Expecting only scalar valued subelement for TensorElement.")
 
         # Set default shape if not specified
         if shape is None:
-            ufl_assert(cell is not None,
-                       "Cannot infer tensor shape without a cell.")
+            if cell is None:
+                error("Cannot infer tensor shape without a cell.")
             dim = cell.geometric_dimension()
             shape = (dim, dim)
 
@@ -358,26 +373,28 @@ class TensorElement(MixedElement):
             symmetry = EmptyDict
         elif symmetry is True:
             # Construct default symmetry dict for matrix elements
-            ufl_assert(len(shape) == 2 and shape[0] == shape[1],
-                       "Cannot set automatic symmetry for non-square tensor.")
-            symmetry = dict( ((i, j), (j, i)) for i in range(shape[0])
-                             for j in range(shape[1]) if i > j )
+            if not (len(shape) == 2 and shape[0] == shape[1]):
+                error("Cannot set automatic symmetry for non-square tensor.")
+            symmetry = dict(((i, j), (j, i)) for i in range(shape[0])
+                            for j in range(shape[1]) if i > j)
         else:
-            ufl_assert(isinstance(symmetry, dict), "Expecting symmetry to be None (unset), True, or dict.")
+            if not isinstance(symmetry, dict):
+                error("Expecting symmetry to be None (unset), True, or dict.")
 
         # Validate indices in symmetry dict
         for i, j in iteritems(symmetry):
-            ufl_assert(len(i) == len(j),
-                       "Non-matching length of symmetry index tuples.")
+            if len(i) != len(j):
+                error("Non-matching length of symmetry index tuples.")
             for k in range(len(i)):
-                ufl_assert(i[k] >= 0 and j[k] >= 0 and
-                           i[k] < shape[k] and j[k] < shape[k],
-                           "Symmetry dimensions out of bounds.")
+                if not (i[k] >= 0 and j[k] >= 0
+                        and i[k] < shape[k] and j[k] < shape[k]):
+                    error("Symmetry dimensions out of bounds.")
 
         # Compute all index combinations for given shape
         indices = compute_indices(shape)
 
-        # Compute mapping from indices to sub element number, accounting for symmetry
+        # Compute mapping from indices to sub element number,
+        # accounting for symmetry
         sub_elements = []
         sub_element_mapping = {}
         for index in indices:
@@ -390,7 +407,8 @@ class TensorElement(MixedElement):
         for index in indices:
             if index in symmetry:
                 sub_element_mapping[index] = sub_element_mapping[symmetry[index]]
-        flattened_sub_element_mapping = [sub_element_mapping[index] for i, index in enumerate(indices)]
+        flattened_sub_element_mapping = [sub_element_mapping[index] for i,
+                                         index in enumerate(indices)]
 
         # Compute value shape
         value_shape = shape
@@ -406,7 +424,8 @@ class TensorElement(MixedElement):
             self._mapping = "identity"
 
         # Initialize element data
-        MixedElement.__init__(self, sub_elements, value_shape=value_shape, reference_value_shape=reference_value_shape)
+        MixedElement.__init__(self, sub_elements, value_shape=value_shape,
+                              reference_value_shape=reference_value_shape)
         self._family = sub_element.family()
         self._degree = sub_element.degree()
         self._sub_element = sub_element
@@ -416,7 +435,8 @@ class TensorElement(MixedElement):
         self._flattened_sub_element_mapping = flattened_sub_element_mapping
 
         # Cache repr string
-        self._repr = "TensorElement(%r, shape=%r, symmetry=%r)" % (sub_element, self._shape, self._symmetry)
+        self._repr = "TensorElement(%s, shape=%s, symmetry=%s)" % (
+            repr(sub_element), repr(self._shape), repr(self._symmetry))
 
     def mapping(self):
         if self._symmetry:
@@ -429,7 +449,7 @@ class TensorElement(MixedElement):
 
     def extract_subelement_component(self, i):
         """Extract direct subelement index and subelement relative
-        component index for a given component index"""
+        component index for a given component index."""
         if isinstance(i, int):
             i = (i,)
         self._check_component(i)
@@ -438,14 +458,16 @@ class TensorElement(MixedElement):
         l = len(self._shape)
         ii = i[:l]
         jj = i[l:]
-        ufl_assert(ii in self._sub_element_mapping,
-                   "Illegal component index %s." % repr(i))
+        if ii not in self._sub_element_mapping:
+            error("Illegal component index %s." % (i,))
         k = self._sub_element_mapping[ii]
         return (k, jj)
 
     def symmetry(self):
-        """Return the symmetry dict, which is a mapping c0 -> c1
-        meaning that component c0 is represented by component c1."""
+        """Return the symmetry dict, which is a mapping :math:`c_0 \\to c_1`
+        meaning that component :math:`c_0` is represented by component
+        :math:`c_1`.
+        A component is a tuple of one or more ints."""
         return self._symmetry
 
     def __str__(self):
diff --git a/ufl/finiteelement/outerproductelement.py b/ufl/finiteelement/outerproductelement.py
deleted file mode 100644
index 2d8014c..0000000
--- a/ufl/finiteelement/outerproductelement.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- coding: utf-8 -*-
-"This module defines the UFL finite element classes."
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Andrew T. T. McRae
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-#
-# Based on tensorproductelement.py
-# Modified by Andrew T. T. McRae 2014
-# Modified by Lawrence Mitchell 2014
-
-from ufl.assertions import ufl_assert
-from ufl.cell import OuterProductCell, as_cell
-from ufl.finiteelement.mixedelement import MixedElement
-from ufl.finiteelement.finiteelementbase import FiniteElementBase
-
-
-class OuterProductElement(FiniteElementBase):
-    r"""The outer (tensor) product of 2 element spaces:
-
-    .. math:: V = A \otimes B
-
-    Given bases :math:`{\phi_A, \phi_B}` for :math:`A, B`,
-    :math:`{\phi_A * \phi_B}` forms a basis for :math:`V`.
-    """
-    __slots__ = ("_A", "_B", "_mapping")
-
-    def __init__(self, A, B, cell=None):
-        "Create OuterProductElement from a given pair of elements."
-        self._A = A
-        self._B = B
-        family = "OuterProductElement"
-
-        if cell is None:
-            # Define cell as the product of sub-cells
-            cell = OuterProductCell(A.cell(), B.cell())
-        else:
-            cell = as_cell(cell)
-
-        self._repr = "OuterProductElement(%r, %r, %r)" % (self._A, self._B, cell)
-
-        # Define polynomial degree as a tuple of sub-degrees
-        degree = (A.degree(), B.degree())
-
-        # match FIAT implementation
-        value_shape = A.value_shape() + B.value_shape()
-        reference_value_shape = A.reference_value_shape() + B.reference_value_shape()
-        ufl_assert(len(value_shape) <= 1, "Product of vector-valued elements not supported")
-        ufl_assert(len(reference_value_shape) <= 1, "Product of vector-valued elements not supported")
-
-        if A.mapping() == "identity" and B.mapping() == "identity":
-            self._mapping = "identity"
-        else:
-            self._mapping = "undefined"
-
-        FiniteElementBase.__init__(self, family, cell, degree,
-                                   None, value_shape, reference_value_shape)
-
-    def mapping(self):
-        return self._mapping
-
-    def __str__(self):
-        "Pretty-print."
-        return "OuterProductElement(%s)" \
-            % str([str(self._A), str(self._B)])
-
-    def shortstr(self):
-        "Short pretty-print."
-        return "OuterProductElement(%s)" \
-            % str([self._A.shortstr(), self._B.shortstr()])
diff --git a/ufl/finiteelement/restrictedelement.py b/ufl/finiteelement/restrictedelement.py
index 2774c1e..18b4bd5 100644
--- a/ufl/finiteelement/restrictedelement.py
+++ b/ufl/finiteelement/restrictedelement.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,31 +20,37 @@
 #
 # Modified by Kristian B. Oelgaard
 # Modified by Marie E. Rognes 2010, 2012
+# Modified by Massimiliano Leoni, 2016
 
-from ufl.assertions import ufl_assert
-from ufl.cell import Cell, as_cell
-from ufl.log import info_blue, warning, warning_blue, error, deprecate
-
+# import six
+from ufl.utils.py23 import as_native_str
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
+from ufl.log import error
 
 valid_restriction_domains = ("interior", "facet", "face", "edge", "vertex")
 
+
+# @six.python_2_unicode_compatible
 class RestrictedElement(FiniteElementBase):
     "Represents the restriction of a finite element to a type of cell entity."
     def __init__(self, element, restriction_domain):
-        ufl_assert(isinstance(element, FiniteElementBase),
-                   "Expecting a finite element instance.")
-        ufl_assert(restriction_domain in valid_restriction_domains,
-                   "Expecting one of the strings %r." % (valid_restriction_domains,))
+        if not isinstance(element, FiniteElementBase):
+            error("Expecting a finite element instance.")
+        if restriction_domain not in valid_restriction_domains:
+            error("Expecting one of the strings %s." % (valid_restriction_domains,))
 
         FiniteElementBase.__init__(self, "RestrictedElement", element.cell(),
-            element.degree(), element.quadrature_scheme(), element.value_shape(), element.reference_value_shape())
+                                   element.degree(),
+                                   element.quadrature_scheme(),
+                                   element.value_shape(),
+                                   element.reference_value_shape())
 
         self._element = element
 
         self._restriction_domain = restriction_domain
 
-        self._repr = "RestrictedElement(%r, %r)" % (self._element, self._restriction_domain)
+        self._repr = as_native_str("RestrictedElement(%s, %s)" % (
+            repr(self._element), repr(self._restriction_domain)))
 
     def is_cellwise_constant(self):
         """Return whether the basis functions of this
@@ -55,9 +61,10 @@ class RestrictedElement(FiniteElementBase):
         "Return the element which is restricted."
         return self._element
 
-    def element(self):
-        deprecate("RestrictedElement.element() is deprecated, please use .sub_element() instead.")
-        return self.sub_element()
+    #def element(self):
+    #    "Deprecated."
+    #    deprecate("RestrictedElement.element() is deprecated, please use .sub_element() instead.")
+    #    return self.sub_element()
 
     def mapping(self):
         return self._element.mapping()
@@ -72,22 +79,23 @@ class RestrictedElement(FiniteElementBase):
 
     def shortstr(self):
         "Format as string for pretty printing."
-        return "<%s>|_{%s}" % (self._element.shortstr(), self._restriction_domain)
+        return "<%s>|_{%s}" % (self._element.shortstr(),
+                               self._restriction_domain)
 
     def symmetry(self):
-        """Return the symmetry dict, which is a mapping c0 -> c1
-        meaning that component c0 is represented by component c1."""
+        """Return the symmetry dict, which is a mapping :math:`c_0 \\to c_1`
+        meaning that component :math:`c_0` is represented by component
+        :math:`c_1`.
+        A component is a tuple of one or more ints."""
         return self._element.symmetry()
 
     def num_sub_elements(self):
-        "Return number of sub elements"
+        "Return number of sub elements."
         return self._element.num_sub_elements()
-        #return 1
 
     def sub_elements(self):
-        "Return list of sub elements"
+        "Return list of sub elements."
         return self._element.sub_elements()
-        #return [self._element]
 
     def num_restricted_sub_elements(self):
         # FIXME: Use this where intended, for disambiguation
diff --git a/ufl/finiteelement/tensorproductelement.py b/ufl/finiteelement/tensorproductelement.py
index 4d15b24..59ccff0 100644
--- a/ufl/finiteelement/tensorproductelement.py
+++ b/ufl/finiteelement/tensorproductelement.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines the UFL finite element classes."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,57 +20,69 @@
 #
 # Modified by Kristian B. Oelgaard
 # Modified by Marie E. Rognes 2010, 2012
+# Modified by Massimiliano Leoni, 2016
 
-from ufl.assertions import ufl_assert
-from ufl.cell import as_cell, TensorProductCell
-from ufl.log import info_blue, warning, warning_blue, error
+# import six
+from itertools import chain
+
+from ufl.log import error
+from ufl.utils.py23 import as_native_strings
+from ufl.cell import TensorProductCell, as_cell
 
 from ufl.finiteelement.finiteelementbase import FiniteElementBase
 
 
+# @six.python_2_unicode_compatible
 class TensorProductElement(FiniteElementBase):
-    r"""The tensor product of d element spaces:
+    r"""The tensor product of :math:`d` element spaces:
 
-    .. math:: V = V_0 \otimes V_1 \otimes ...  \otimes V_d
+    .. math:: V = V_1 \otimes V_2 \otimes ...  \otimes V_d
 
-    Given bases {phi_i} for V_i for i = 1, ...., d,
-    { phi_0 * phi_1 * ... * phi_d } forms a basis for V.
+    Given bases :math:`\{\phi_{j_i}\}` of the spaces :math:`V_i` for :math:`i = 1, ...., d`,
+    :math:`\{ \phi_{j_1} \otimes \phi_{j_2} \otimes \cdots \otimes \phi_{j_d}
+    \}` forms a basis for :math:`V`.
     """
-    __slots__ = ("_sub_elements",)
+    __slots__ = as_native_strings(("_sub_elements", "_cell"))
 
-    def __init__(self, elements):
+    def __init__(self, *elements, **kwargs):
         "Create TensorProductElement from a given list of elements."
+        if not elements:
+            error("Cannot create TensorProductElement from empty list.")
 
-        warning("The TensorProductElement is work in progress and the design may change at any moment without notice.")
-
-        self._sub_elements = elements
-        ufl_assert(len(self._sub_elements) > 0,
-                   "Cannot create TensorProductElement from empty list.")
-        self._repr = "TensorProductElement(%s)" % ", ".join(repr(e) for e in self._sub_elements)
+        keywords = list(kwargs.keys())
+        if keywords and keywords != ["cell"]:
+            raise ValueError("TensorProductElement got an unexpected keyword argument '%s'" % keywords[0])
+        cell = kwargs.get("cell")
 
         family = "TensorProductElement"
 
-        # Define cell as the product of each elements cell
-        cell = TensorProductCell([e.cell() for e in self._sub_elements])
+        if cell is None:
+            # Define cell as the product of each elements cell
+            cell = TensorProductCell(*[e.cell() for e in elements])
+        else:
+            cell = as_cell(cell)
 
-        # Define polynomial degree as the maximal of each subelement
-        degrees = { e.degree() for e in self._sub_elements } - { None }
-        degree = max(degrees) if degrees else None
+        # Define polynomial degree as a tuple of sub-degrees
+        degree = tuple(e.degree() for e in elements)
 
         # No quadrature scheme defined
         quad_scheme = None
 
-        # For now, check that all subelements have the same value
-        # shape, and use this.
-        # TODO: Not sure if this makes sense, what kind of product is used to build the basis?
-        value_shape = self._sub_elements[0].value_shape()
-        reference_value_shape = self._sub_elements[0].reference_value_shape()
-        ufl_assert(all(e.value_shape() == value_shape
-                       for e in self._sub_elements),
-                   "All subelements in must have same value shape")
+        # match FIAT implementation
+        value_shape = tuple(chain(*[e.value_shape() for e in elements]))
+        reference_value_shape = tuple(chain(*[e.reference_value_shape() for e in elements]))
+        if len(value_shape) > 1:
+            error("Product of vector-valued elements not supported")
+        if len(reference_value_shape) > 1:
+            error("Product of vector-valued elements not supported")
 
         FiniteElementBase.__init__(self, family, cell, degree,
-                                   quad_scheme, value_shape, reference_value_shape)
+                                   quad_scheme, value_shape,
+                                   reference_value_shape)
+        self._sub_elements = elements
+        self._cell = cell
+        self._repr = "TensorProductElement(%s, cell=%s)" % (
+            ", ".join(repr(e) for e in elements), repr(cell))
 
     def mapping(self):
         if all(e.mapping() == "identity" for e in self._sub_elements):
@@ -88,10 +100,10 @@ class TensorProductElement(FiniteElementBase):
 
     def __str__(self):
         "Pretty-print."
-        return "TensorProductElement(%s)" \
-            % str([str(e) for e in self.sub_elements()])
+        return "TensorProductElement(%s, cell=%s)" \
+            % (', '.join([str(e) for e in self._sub_elements]), str(self._cell))
 
     def shortstr(self):
         "Short pretty-print."
-        return "TensorProductElement(%s)" \
-            % str([e.shortstr() for e in self.sub_elements()])
+        return "TensorProductElement(%s, cell=%s)" \
+            % (', '.join([e.shortstr() for e in self._sub_elements]), str(self._cell))
diff --git a/ufl/finiteelement/traceelement.py b/ufl/finiteelement/traceelement.py
deleted file mode 100644
index 26bd238..0000000
--- a/ufl/finiteelement/traceelement.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (C) 2014 Andrew T. T. McRae
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
-from ufl.finiteelement.finiteelementbase import FiniteElementBase
-
-class TraceElement(FiniteElementBase):
-    """A finite element space: the trace of a given hdiv element.
-    This is effectively a scalar-valued restriction which is
-    non-zero only on cell facets."""
-
-    def __init__(self, element):
-        self._element = element
-        self._repr = "TraceElement(%s)" % repr(element)
-
-        family = "TraceElement"
-        cell = element.cell()
-        degree = element.degree()
-        quad_scheme = element.quadrature_scheme()
-        value_shape = ()
-        reference_value_shape = ()
-        FiniteElementBase.__init__(self, family, cell, degree,
-                                   quad_scheme, value_shape, reference_value_shape)
-
-    def mapping(self):
-        return "identity"
-
-    def __str__(self):
-        return "TraceElement(%s)" % str(self._element)
-
-    def shortstr(self):
-        return "TraceElement(%s)" % str(self._element.shortstr())
-
-    def __repr__(self):
-        return self._repr
diff --git a/ufl/form.py b/ufl/form.py
index 301799c..e88a288 100644
--- a/ufl/form.py
+++ b/ufl/form.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "The Form class."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,32 +19,34 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2009-2011.
+# Modified by Massimiliano Leoni, 2016.
 
-import hashlib
+# import six
 from itertools import chain
 from collections import defaultdict
-from ufl.log import error, deprecate
-from ufl.assertions import ufl_assert
-import ufl.measure
-from ufl.integral import Integral, Measure
+
+from ufl.log import error, warning
+from ufl.integral import Integral
 from ufl.checks import is_scalar_constant_expression
 from ufl.equation import Equation
 from ufl.core.expr import Expr
+from ufl.core.expr import ufl_err_str
 from ufl.constantvalue import Zero
-from ufl.protocols import id_or_none
-from ufl.coefficient import Coefficient
+from ufl.utils.py23 import as_native_strings, as_native_str
 
 # Export list for ufl.classes
-__all_classes__ = ["Form"]
+__all_classes__ = as_native_strings(["Form"])
 
 # --- The Form class, representing a complete variational form or functional ---
 
+
 def _sorted_integrals(integrals):
     """Sort integrals by domain id, integral type, subdomain id
     for a more stable signature computation."""
 
-    # Group integrals in multilevel dict by keys [domain][integral_type][subdomain_id]
-    integrals_dict = defaultdict(lambda:defaultdict(lambda:defaultdict(list)))
+    # Group integrals in multilevel dict by keys
+    # [domain][integral_type][subdomain_id]
+    integrals_dict = defaultdict(lambda: defaultdict(lambda: defaultdict(list)))
     for integral in integrals:
         d = integral.ufl_domain()
         if d is None:
@@ -56,19 +58,25 @@ def _sorted_integrals(integrals):
     all_integrals = []
 
     # Order integrals canonically to increase signature stability
-    for d in sorted(integrals_dict): # Assuming Domain is sortable
-        for it in sorted(integrals_dict[d]): # str is sortable
-            for si in sorted(integrals_dict[d][it], key=lambda x: (type(x).__name__, x)): # int/str are sortable
+    for d in sorted(integrals_dict):  # Assuming Domain is sortable
+        for it in sorted(integrals_dict[d]):  # str is sortable
+            for si in sorted(integrals_dict[d][it],
+                             key=lambda x: (type(x).__name__, x)):  # int/str are sortable
                 unsorted_integrals = integrals_dict[d][it][si]
-                # TODO: At this point we could order integrals by metadata and integrand,
-                #       or even add the integrands with the same metadata. This is done
-                #       in accumulate_integrands_with_same_metadata in algorithms/domain_analysis.py
-                #       and would further increase the signature stability.
+                # TODO: At this point we could order integrals by
+                #       metadata and integrand, or even add the
+                #       integrands with the same metadata. This is
+                #       done in
+                #       accumulate_integrands_with_same_metadata in
+                #       algorithms/domain_analysis.py and would
+                #       further increase the signature stability.
                 all_integrals.extend(unsorted_integrals)
-                #integrals_dict[d][it][si] = unsorted_integrals
+                # integrals_dict[d][it][si] = unsorted_integrals
 
-    return tuple(all_integrals) #, integrals_dict
+    return tuple(all_integrals)  # integrals_dict
 
+
+# @six.python_2_unicode_compatible
 class Form(object):
     """Description of a weak form consisting of a sum of integrals over subdomains."""
     __slots__ = (
@@ -87,14 +95,16 @@ class Form(object):
         #     data in to be carried with the form
         #     Never use this internally in ufl!
         "_cache",
-        )
+    )
 
     def __init__(self, integrals):
-        # Basic input checking (further compatibilty analysis happens later)
-        ufl_assert(all(isinstance(itg, Integral) for itg in integrals),
-                   "Expecting list of integrals.")
+        # Basic input checking (further compatibilty analysis happens
+        # later)
+        if not all(isinstance(itg, Integral) for itg in integrals):
+            error("Expecting list of integrals.")
 
-        # Store integrals sorted canonically to increase signature stability
+        # Store integrals sorted canonically to increase signature
+        # stability
         self._integrals = _sorted_integrals(integrals)
 
         # Internal variables for caching domain data
@@ -109,7 +119,8 @@ class Form(object):
         self._coefficients = None
         self._coefficient_numbering = None
 
-        # Internal variables for caching of hash and signature after first request
+        # Internal variables for caching of hash and signature after
+        # first request
         self._hash = None
         self._signature = None
 
@@ -127,17 +138,14 @@ class Form(object):
         return tuple(integral for integral in self.integrals()
                      if integral.integral_type() == integral_type)
 
-    #def integrals_dict(self):
-    #    "Returns a mapping on the form { domain: { integral_type: { subdomain_id: integral_list } } }."
-    #    return self._integrals_dict
-
     def empty(self):
         "Returns whether the form has no integrals."
         return self.integrals() == ()
 
-    def domains(self):
-        deprecate("Form.domains() is deprecated, please use .ufl_domains() instead.")
-        return self.ufl_domains()
+    #def domains(self):
+    #    "Deprecated, please use .ufl_domains() instead."
+    #    deprecate("Form.domains() is deprecated, please use .ufl_domains() instead.")
+    #    return self.ufl_domains()
 
     def ufl_domains(self):
         """Return the geometric integration domains occuring in the form.
@@ -150,13 +158,15 @@ class Form(object):
             self._analyze_domains()
         return self._integration_domains
 
-    def cell(self):
-        deprecate("Form.cell() is deprecated, please use .ufl_cell() instead.")
-        return self.ufl_cell()
+    #def cell(self):
+    #    "Deprecated, please use .ufl_cell() instead."
+    #    deprecate("Form.cell() is deprecated, please use .ufl_cell() instead.")
+    #    return self.ufl_cell()
 
-    def domain(self):
-        deprecate("Form.domain() is deprecated, please use .ufl_domain() instead.")
-        return self.ufl_domain()
+    #def domain(self):
+    #    "Deprecated, please use .ufl_domain() instead."
+    #    deprecate("Form.domain() is deprecated, please use .ufl_domain() instead.")
+    #    return self.ufl_domain()
 
     def ufl_cell(self):
         "Return the single cell this form is defined on, fails if multiple cells are found."
@@ -172,51 +182,58 @@ class Form(object):
         """
         # Collect all domains
         domains = self.ufl_domains()
-        # Check that all are equal TODO: don't return more than one if all are equal?
-        ufl_assert(all(domain == domains[0] for domain in domains),
-                   "Calling Form.ufl_domain() is only valid if all integrals share domain.")
+        # Check that all are equal TODO: don't return more than one if
+        # all are equal?
+        if not all(domain == domains[0] for domain in domains):
+            error("Calling Form.ufl_domain() is only valid if all integrals share domain.")
         # Return the one and only domain
         return domains[0]
 
     def geometric_dimension(self):
         "Return the geometric dimension shared by all domains and functions in this form."
-        gdims = tuple(set(domain.geometric_dimension() for domain in self.ufl_domains()))
-        ufl_assert(len(gdims) == 1,
-                  "Expecting all domains and functions in a form to share geometric dimension, got %s." % str(tuple(sorted(gdims))))
+        gdims = tuple(set(domain.geometric_dimension()
+                          for domain in self.ufl_domains()))
+        if len(gdims) != 1:
+            error("Expecting all domains and functions in a form "
+                  "to share geometric dimension, got %s." % str(tuple(sorted(gdims))))
         return gdims[0]
 
     def domain_numbering(self):
-        "Return a contiguous numbering of domains in a mapping { domain: number }."
+        """Return a contiguous numbering of domains in a mapping
+        ``{domain:number}``."""
         if self._domain_numbering is None:
             self._analyze_domains()
         return self._domain_numbering
 
     def subdomain_data(self):
-        "Returns a mapping on the form { domain: { integral_type: subdomain_data } }."
+        """Returns a mapping on the form ``{domain:{integral_type:
+            subdomain_data}}``."""
         if self._subdomain_data is None:
             self._analyze_subdomain_data()
         return self._subdomain_data
 
     def max_subdomain_ids(self):
-        "Returns a mapping on the form { domain: { integral_type: max_subdomain_id } }."
+        """Returns a mapping on the form
+        ``{domain:{integral_type:max_subdomain_id}}``."""
         if self._max_subdomain_ids is None:
             self._analyze_subdomain_data()
         return self._max_subdomain_ids
 
     def arguments(self):
-        "Return all Argument objects found in form."
+        "Return all ``Argument`` objects found in form."
         if self._arguments is None:
             self._analyze_form_arguments()
         return self._arguments
 
     def coefficients(self):
-        "Return all Coefficient objects found in form."
+        "Return all ``Coefficient`` objects found in form."
         if self._coefficients is None:
             self._analyze_form_arguments()
         return self._coefficients
 
     def coefficient_numbering(self):
-        "Return a contiguous numbering of coefficients in a mapping { coefficient: number }."
+        """Return a contiguous numbering of coefficients in a mapping
+        ``{coefficient:number}``."""
         if self._coefficient_numbering is None:
             self._analyze_form_arguments()
         return self._coefficient_numbering
@@ -249,7 +266,7 @@ class Form(object):
         return not self.equals(other)
 
     def equals(self, other):
-        "Evaluate 'bool(lhs_form == rhs_form)'."
+        "Evaluate ``bool(lhs_form == rhs_form)``."
         if type(other) != Form:
             return False
         if len(self._integrals) != len(other._integrals):
@@ -303,35 +320,93 @@ class Form(object):
 
     def __mul__(self, coefficient):
         "UFL form operator: Take the action of this form on the given coefficient."
-        if isinstance(coefficient, Expr): #Coefficient): # TODO: Check whatever makes sense
+        if isinstance(coefficient, Expr):
             from ufl.formoperators import action
             return action(self, coefficient)
         return NotImplemented
 
+    def __call__(self, *args, **kwargs):
+        """UFL form operator: Evaluate form by replacing arguments and coefficients.
+
+        Replaces form.arguments() with given positional arguments
+        in same number and ordering. Number of positional arguments
+        must be 0 or equal to the number of Arguments in the form.
+
+        The optional keyword argument coefficients can be set to a dict
+        to replace Coefficients with expressions of matching shapes.
+
+        Example:
+
+          V = FiniteElement("CG", triangle, 1)
+          v = TestFunction(V)
+          u = TrialFunction(V)
+          f = Coefficient(V)
+          g = Coefficient(V)
+          a = g*inner(grad(u), grad(v))*dx
+          M = a(f, f, coefficients={ g: 1 })
+
+        Is equivalent to M == grad(f)**2*dx.
+        """
+        repdict = {}
+
+        if args:
+            arguments = self.arguments()
+            if len(arguments) != len(args):
+                error("Need %d arguments to form(), got %d." % (len(arguments), len(args)))
+            repdict.update(zip(arguments, args))
+
+        coefficients = kwargs.pop("coefficients")
+        if kwargs:
+            error("Unknown kwargs %s." % str(list(kwargs)))
+
+        if coefficients is not None:
+            coeffs = self.coefficients()
+            for f in coefficients:
+                if f in coeffs:
+                    repdict[f] = coefficients[f]
+                else:
+                    warning("Coefficient %s is not in form." % ufl_err_str(f))
+        if repdict:
+            from ufl.formoperators import replace
+            return replace(self, repdict)
+        else:
+            return self
+
+    # "a @ f" notation in python 3.5
+    __matmul__ = __mul__
+
     # --- String conversion functions, for UI purposes only ---
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         "Compute shorter string representation of form. This can be huge for complicated forms."
-        # TODO: Add warning here to check if anyone actually calls it in libraries
+        # Warning used for making sure we don't use this in the general pipeline:
+        #warning("Calling str on form is potentially expensive and should be avoided except during debugging.")
+        # Not caching this because it can be huge
         s = "\n  +  ".join(str(itg) for itg in self.integrals())
         return s or "<empty Form>"
 
     def __repr__(self):
         "Compute repr string of form. This can be huge for complicated forms."
-        # TODO: Add warning here to check if anyone actually calls it in libraries
+        # Warning used for making sure we don't use this in the general pipeline:
+        #warning("Calling repr on form is potentially expensive and should be avoided except during debugging.")
         # Not caching this because it can be huge
-        r = "Form([%s])" % ", ".join(repr(itg) for itg in self.integrals())
-        return r
+        itgs = ", ".join(repr(itg) for itg in self.integrals())
+        r = "Form([" + itgs + "])"
+        return as_native_str(r)
 
-    def x_repr_latex_(self): # TODO: This works, but enable when form latex rendering is fixed
+    def x_repr_latex_(self):  # TODO: This works, but enable when form latex rendering is fixed
         from ufl.algorithms import ufl2latex
         return "$$%s$$" % ufl2latex(self)
 
-    def x_repr_png_(self): # TODO: This works, but enable when form latex rendering is fixed
+    def x_repr_png_(self):  # TODO: This works, but enable when form latex rendering is fixed
         from IPython.lib.latextools import latex_to_png
         return latex_to_png(self._repr_latex_())
 
-    # --- Analysis functions, precomputation and caching of various quantities ---
+    # --- Analysis functions, precomputation and caching of various quantities
 
     def _analyze_domains(self):
         from ufl.domain import join_domains, sort_domains
@@ -342,7 +417,8 @@ class Form(object):
         # Make canonically ordered list of the domains
         self._integration_domains = sort_domains(integration_domains)
 
-        # TODO: Not including domains from coefficients and arguments here, may need that later
+        # TODO: Not including domains from coefficients and arguments
+        # here, may need that later
         self._domain_numbering = dict((d, i) for i, d in enumerate(self._integration_domains))
 
     def _analyze_subdomain_data(self):
@@ -365,7 +441,8 @@ class Form(object):
             if data is None:
                 subdomain_data[domain][it] = sd
             elif sd is not None:
-                ufl_assert(data.ufl_id() == sd.ufl_id(), "Integrals in form have different subdomain_data objects.")
+                if data.ufl_id() != sd.ufl_id():
+                    error("Integrals in form have different subdomain_data objects.")
         self._subdomain_data = subdomain_data
 
     def _analyze_form_arguments(self):
@@ -374,9 +451,12 @@ class Form(object):
         arguments, coefficients = extract_arguments_and_coefficients(self)
 
         # Define canonical numbering of arguments and coefficients
-        self._arguments = tuple(sorted(set(arguments), key=lambda x: x.number()))
-        self._coefficients = tuple(sorted(set(coefficients), key=lambda x: x.count()))
-        self._coefficient_numbering = dict((c, i) for i, c in enumerate(self._coefficients))
+        self._arguments = tuple(sorted(set(arguments),
+                                       key=lambda x: x.number()))
+        self._coefficients = tuple(sorted(set(coefficients),
+                                          key=lambda x: x.count()))
+        self._coefficient_numbering = dict((c, i) for i,
+                                           c in enumerate(self._coefficients))
 
     def _compute_renumbering(self):
         # Include integration domains and coefficients in renumbering
@@ -386,7 +466,8 @@ class Form(object):
         renumbering.update(dn)
         renumbering.update(cn)
 
-        # Add domains of coefficients, these may include domains not among integration domains
+        # Add domains of coefficients, these may include domains not
+        # among integration domains
         k = len(dn)
         for c in cn:
             d = c.ufl_domain()
@@ -398,31 +479,32 @@ class Form(object):
 
     def _compute_signature(self):
         from ufl.algorithms.signature import compute_form_signature
-        self._signature = compute_form_signature(self, self._compute_renumbering())
+        self._signature = compute_form_signature(self,
+                                                 self._compute_renumbering())
 
 
 def as_form(form):
     "Convert to form if not a form, otherwise return form."
     if not isinstance(form, Form):
-        error("Unable to convert object to a UFL form: %s" % repr(form))
+        error("Unable to convert object to a UFL form: %s" % ufl_err_str(form))
     return form
 
 
-def replace_integral_domains(form, common_domain): # TODO: Move elsewhere
+def replace_integral_domains(form, common_domain):  # TODO: Move elsewhere
     """Given a form and a domain, assign a common integration domain to all integrals.
 
-    Does not modify the input form (Form should always be immutable).
+    Does not modify the input form (``Form`` should always be immutable).
     This is to support ill formed forms with no domain specified,
-    some times occuring in pydolfin, e.g. assemble(1*dx, mesh=mesh).
+    sometimes occurring in pydolfin, e.g. assemble(1*dx, mesh=mesh).
     """
     domains = form.ufl_domains()
     if common_domain is not None:
         gdim = common_domain.geometric_dimension()
         tdim = common_domain.topological_dimension()
-        ufl_assert(all((gdim == domain.geometric_dimension() and
-                        tdim == domain.topological_dimension())
-                        for domain in domains),
-            "Common domain does not share dimensions with form domains.")
+        if not all((gdim == domain.geometric_dimension() and
+                    tdim == domain.topological_dimension())
+                   for domain in domains):
+            error("Common domain does not share dimensions with form domains.")
 
     reconstruct = False
     integrals = []
diff --git a/ufl/formatting/graph.py b/ufl/formatting/graph.py
index 4096769..db27f6c 100644
--- a/ufl/formatting/graph.py
+++ b/ufl/formatting/graph.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Algorithms for working with linearized computational graphs."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,24 +21,27 @@
 from collections import defaultdict
 from six.moves import xrange as range
 from six.moves import map
-from heapq import heapify, heappop, heappush
+from heapq import heapify, heappop
 
 from ufl.corealg.traversal import unique_pre_traversal
 from ufl.corealg.multifunction import MultiFunction
 
 # O(n) = O(|V|) = O(|E|), since |E| < c|V| for a fairly small c.
 
-#--- Basic utility functions ---
+
+# --- Basic utility functions ---
 
 def lists(n):
     return [[] for i in range(n)]
 
+
 def len_items(sequence):
     return list(map(len, sequence))
 
-#--- Graph building functions ---
 
-def build_graph(expr): # O(n)
+# --- Graph building functions ---
+
+def build_graph(expr):  # O(n)
     """Build a linearized graph from an UFL Expr.
 
     Returns G = (V, E), with V being a list of
@@ -50,7 +53,6 @@ def build_graph(expr): # O(n)
     V = []
     E = []
     handled = {}
-    #for v in post_traversal(expr):
     for v in reversed(list(unique_pre_traversal(expr))):
         i = handled.get(v)
         if i is None:
@@ -64,7 +66,8 @@ def build_graph(expr): # O(n)
     G = V, E
     return G
 
-def extract_incoming_edges(G): # O(n)
+
+def extract_incoming_edges(G):  # O(n)
     "Build lists of incoming edges to each vertex in a linearized graph."
     V, E = G
     n = len(V)
@@ -73,7 +76,8 @@ def extract_incoming_edges(G): # O(n)
         Ein[e[1]].append(i)
     return Ein
 
-def extract_outgoing_edges(G): # O(n)
+
+def extract_outgoing_edges(G):  # O(n)
     "Build list of outgoing edges from each vertex in a linearized graph."
     V, E = G
     n = len(V)
@@ -82,19 +86,21 @@ def extract_outgoing_edges(G): # O(n)
         Eout[e[0]].append(i)
     return Eout
 
-def extract_incoming_vertex_connections(G): # O(n)
+
+def extract_incoming_vertex_connections(G):  # O(n)
     """Build lists of vertices in incoming and outgoing
     edges to and from each vertex in a linearized graph.
 
     Returns lists Vin and Vout."""
     V, E = G
     n = len(V)
-    Vin  = lists(n)
+    Vin = lists(n)
     for a, b in E:
         Vin[b].append(a)
     return Vin
 
-def extract_outgoing_vertex_connections(G): # O(n)
+
+def extract_outgoing_vertex_connections(G):  # O(n)
     """Build lists of vertices in incoming and outgoing
     edges to and from each vertex in a linearized graph.
 
@@ -107,7 +113,7 @@ def extract_outgoing_vertex_connections(G): # O(n)
     return Vout
 
 
-#--- Graph class ---
+# --- Graph class ---
 
 class Graph:
     "Graph class which computes connectivity on demand."
@@ -147,7 +153,8 @@ class Graph:
     def __iter__(self):
         return iter((self._V, self._E))
 
-#--- Scheduling algorithms ---
+
+# --- Scheduling algorithms ---
 
 class HeapItem(object):
     def __init__(self, incoming, outgoing, i):
@@ -190,13 +197,16 @@ def depth_first_ordering(G):
         ordering.append(iv)
         for i in Vin[iv]:
             Eout_count[i] -= 1
-        # Resort heap, worst case linear time, makes this algorithm O(n^2)... TODO: Not good!
+        # Resort heap, worst case linear time, makes this algorithm
+        # O(n^2)... TODO: Not good!
         heapify(q)
 
-    # TODO: Can later accumulate dependencies as well during dft-like algorithm.
+    # TODO: Can later accumulate dependencies as well during dft-like
+    # algorithm.
     return ordering
 
-#--- Graph partitoning ---
+
+# --- Graph partitoning ---
 
 class StringDependencyDefiner(MultiFunction):
     """Given an expr, returns a frozenset of its dependencies.
@@ -206,7 +216,7 @@ class StringDependencyDefiner(MultiFunction):
         "x"       - depends on local coordinates
         "v%d" % i - depends on argument i, for i in [0,rank)
     """
-    def __init__(self, argument_deps = None, coefficient_deps = None):
+    def __init__(self, argument_deps=None, coefficient_deps=None):
         MultiFunction.__init__(self)
         if argument_deps is None:
             argument_deps = {}
@@ -219,7 +229,7 @@ class StringDependencyDefiner(MultiFunction):
         return frozenset()
 
     def argument(self, x):
-        default = frozenset(("v%d" % x.number(), "x")) # TODO: This is missing the part, but this code is ready for deletion anyway?
+        default = frozenset(("v%d" % x.number(), "x"))  # TODO: This is missing the part, but this code is ready for deletion anyway?
         return self.argument_deps.get(x, default)
 
     def coefficient(self, x):
@@ -234,19 +244,22 @@ class StringDependencyDefiner(MultiFunction):
         deps = frozenset(("c",))
         # Enabling coordinate dependency for higher order geometries
         # (not handled anywhere else though, so consider this experimental)
-        #if o.has_higher_degree_cell_geometry():
-        #    deps = deps | frozenset(("x",))
+        # if o.has_higher_degree_cell_geometry():
+        #     deps = deps | frozenset(("x",))
         return deps
 
-    def spatial_derivative(self, o): # TODO: What about (basis) functions of which derivatives are constant? Should special-case spatial_derivative in partition().
+    def spatial_derivative(self, o):  # TODO: What about (basis) functions of which derivatives are constant? Should special-case spatial_derivative in partition().
         deps = frozenset(("c",))
-        # Enabling coordinate dependency for higher order geometries (not handled anywhere else though).
-        #if o.has_higher_degree_cell_geometry():
-        #    deps = deps | frozenset(("x",))
+        # Enabling coordinate dependency for higher order geometries
+        # (not handled anywhere else though).
+        # if o.has_higher_degree_cell_geometry():
+        #     deps = deps | frozenset(("x",))
         return deps
 
+
 dd = StringDependencyDefiner()
 
+
 def string_set_criteria(v, keys):
     # Using sets of ufl objects
     key = dd(v)
@@ -254,6 +267,7 @@ def string_set_criteria(v, keys):
         key |= k
     return frozenset(key)
 
+
 def partition(G, criteria=string_set_criteria):
     V, E = G
     n = len(V)
diff --git a/ufl/formatting/latextools.py b/ufl/formatting/latextools.py
index 40991c0..05d97a4 100644
--- a/ufl/formatting/latextools.py
+++ b/ufl/formatting/latextools.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module defines basic utilities for stitching together LaTeX documents."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,6 +18,8 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+from six import string_types
+
 # --- Basic LaTeX tools ---
 
 documenttemplate = """\
@@ -66,12 +68,14 @@ verbatimtemplate = """\
 \\end{verbatim}
 """
 
+
 def verbatim(string):
     return verbatimtemplate % string
 
+
 def align(lines):
     # Calculate column lengths
-    if isinstance(lines[0], str):
+    if isinstance(lines[0], string_types):
         body = " \\\\\n".join(l for l in lines)
     else:
         n = len(lines[0])
@@ -79,17 +83,20 @@ def align(lines):
         for l in lines:
             for i, s in enumerate(l):
                 collengths[i] = max(collengths[i], len(s))
+
         def coljoin(cols):
             return " & ".join(c.ljust(collengths[i]) for (i, c) in enumerate(cols))
         body = " \\\\\n".join(coljoin(l) for l in lines)
     return aligntemplate % body
 
+
 def itemize(items):
     body = "\n".join(items)
     return itemizetemplate % body
 
+
 def subsubsection(s):
-    if isinstance(s, str):
+    if isinstance(s, string_types):
         return s
     if isinstance(s, tuple):
         title, body = s
@@ -97,8 +104,9 @@ def subsubsection(s):
             body = itemize(list(map(str, body)))
         return subsubsectiontemplate % (title, body)
 
+
 def subsection(s):
-    if isinstance(s, str):
+    if isinstance(s, string_types):
         return s
     if isinstance(s, tuple):
         title, body = s
@@ -106,8 +114,9 @@ def subsection(s):
             body = "\n".join(subsubsection(ss) for ss in body)
         return subsectiontemplate % (title, body)
 
+
 def section(s):
-    if isinstance(s, str):
+    if isinstance(s, string_types):
         return s
     if isinstance(s, tuple):
         title, body = s
@@ -115,10 +124,12 @@ def section(s):
             body = "\n".join(subsection(ss) for ss in body)
         return sectiontemplate % (title, body)
 
+
 def document(title, sections):
     body = "\n".join(section(s) for s in sections)
     return documenttemplate % (title, body)
 
+
 def testdocument():
     title = "Test title 1"
     sections = ["sec1", "sec2"]
@@ -135,8 +146,7 @@ def testdocument():
     sections = [("sec1", section1), ("sec2", section2), ("sec3", section3)]
     print(document(title, sections))
 
-    matrix = [ ("a(...) ", "= \\int_\\Omega foo dx0"),
-               ("",        "+ \\int_\\Omega foo dx1"),
-               ("",        "+ \\int_\\Omega foo dx1"),
-            ]
+    matrix = [("a(...) ", "= \\int_\\Omega foo dx0"),
+              ("", "+ \\int_\\Omega foo dx1"),
+              ("", "+ \\int_\\Omega foo dx1"), ]
     print(align(matrix))
diff --git a/ufl/formatting/printing.py b/ufl/formatting/printing.py
index 1b27057..37070c3 100644
--- a/ufl/formatting/printing.py
+++ b/ufl/formatting/printing.py
@@ -2,7 +2,7 @@
 """A collection of utility algorithms for printing
 of UFL objects, mostly intended for debugging purposes."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,43 +21,39 @@ of UFL objects, mostly intended for debugging purposes."""
 #
 # Modified by Anders Logg 2009, 2014
 
-from itertools import chain
-
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.core.expr import Expr
-from ufl.core.terminal import Terminal
 from ufl.form import Form
-from ufl.integral import Integral, Measure
+from ufl.integral import Integral
+
 
-#--- Utilities for constructing informative strings from UFL objects ---
+# --- Utilities for constructing informative strings from UFL objects
 
 def integral_info(integral):
-    ufl_assert(isinstance(integral, Integral), "Expecting an Integral.")
-    s  = "  Integral:\n"
+    if not isinstance(integral, Integral):
+        error("Expecting an Integral.")
+    s = "  Integral:\n"
     s += "    Type:\n"
     s += "      %s\n" % integral.integral_type()
     s += "    Domain:\n"
-    s += "      %r\n" % integral.ufl_domain()
+    s += "      %s\n" % integral.ufl_domain()
     s += "    Domain id:\n"
-    s += "      %r\n" % integral.subdomain_id()
+    s += "      %s\n" % integral.subdomain_id()
     s += "    Domain data:\n"
     s += "      %s\n" % integral.subdomain_data()
     s += "    Compiler metadata:\n"
     s += "      %s\n" % integral.metadata()
-    s += "    Integrand expression representation:\n"
-    s += "      %r\n" % integral.integrand()
-    s += "    Integrand expression short form:\n"
-    s += "      %s" % integral.integrand()
     return s
 
+
 def form_info(form):
-    ufl_assert(isinstance(form, Form), "Expecting a Form.")
+    if not isinstance(form, Form):
+        error("Expecting a Form.")
 
     bf = form.arguments()
     cf = form.coefficients()
 
-    s  = "Form info:\n"
+    s = "Form info:\n"
     s += "  rank:                          %d\n" % len(bf)
     s += "  num_coefficients:              %d\n" % len(cf)
     s += "\n"
@@ -83,23 +79,26 @@ def form_info(form):
 
     return s
 
+
 def _indent_string(n):
     return "    "*n
 
+
 def _tree_format_expression(expression, indentation, parentheses):
     ind = _indent_string(indentation)
     if expression._ufl_is_terminal_:
-        s = ind + "%s" % repr(expression)
+        s = "%s%s" % (ind, repr(expression))
     else:
         sops = [_tree_format_expression(o, indentation+1, parentheses) for o in expression.ufl_operands]
-        s = ind + "%s\n" % expression._ufl_class_.__name__
+        s = "%s%s\n" % (ind, expression._ufl_class_.__name__)
         if parentheses and len(sops) > 1:
-            s += ind + "(\n"
+            s += "%s(\n" % (ind,)
         s += "\n".join(sops)
         if parentheses and len(sops) > 1:
-            s += "\n" + ind + ")"
+            s += "\n%s)" % (ind,)
     return s
 
+
 def tree_format(expression, indentation=0, parentheses=True):
     s = ""
 
diff --git a/ufl/formatting/ufl2dot.py b/ufl/formatting/ufl2dot.py
index 82e23c5..5fdca14 100644
--- a/ufl/formatting/ufl2dot.py
+++ b/ufl/formatting/ufl2dot.py
@@ -3,7 +3,7 @@
 of UFL objects in the DOT graph visualization language,
 mostly intended for debugging purposers."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,29 +20,27 @@ mostly intended for debugging purposers."""
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
-from itertools import chain
-
 from six import itervalues
 from six.moves import xrange as range
 
 from ufl.log import error
 from ufl.core.expr import Expr
-from ufl.core.terminal import Terminal
 from ufl.form import Form
-from ufl.integral import Measure
 from ufl.variable import Variable
-from ufl.constantvalue import ScalarValue
-from ufl.classes import FormArgument, MultiIndex, NegativeRestricted, PositiveRestricted
 from ufl.algorithms.multifunction import MultiFunction
 
+
 class ReprLabeller(MultiFunction):
     def __init__(self):
         MultiFunction.__init__(self)
+
     def terminal(self, e):
         return repr(e)
+
     def operator(self, e):
         return e._ufl_class_.__name__.split(".")[-1]
 
+
 class CompactLabeller(ReprLabeller):
     def __init__(self, function_mapping=None):
         ReprLabeller.__init__(self)
@@ -51,10 +49,13 @@ class CompactLabeller(ReprLabeller):
     # Terminals:
     def scalar_value(self, e):
         return repr(e._value)
+
     def zero(self, e):
         return "0"
+
     def identity(self, e):
         return "Id"
+
     def multi_index(self, e):
         return str(e)
 
@@ -67,81 +68,107 @@ class CompactLabeller(ReprLabeller):
     # Operators:
     def sum(self, e):
         return "+"
+
     def product(self, e):
         return "*"
+
     def division(self, e):
         return "/"
+
     def power(self, e):
         return "**"
+
     def math_function(self, e):
         return e._name
+
     def index_sum(self, e):
         return "∑"
+
     def indexed(self, e):
         return "[]"
-    def component_tensor(self, e): # TODO: Understandable short notation for this?
+
+    def component_tensor(self, e):  # TODO: Understandable short notation for this?
         return "]["
+
     def negative_restricted(self, e):
         return "[-]"
+
     def positive_restricted(self, e):
         return "[+]"
-    def cell_avg(self, e): # TODO: Understandable short notation for this?
+
+    def cell_avg(self, e):  # TODO: Understandable short notation for this?
         return "_K_"
-    def facet_avg(self, e): # TODO: Understandable short notation for this?
+
+    def facet_avg(self, e):  # TODO: Understandable short notation for this?
         return "_F_"
 
     def inner(self, e):
         return "inner"
+
     def dot(self, e):
         return "dot"
+
     def outer(self, e):
         return "outer"
+
     def transposed(self, e):
         return "transp."
+
     def determinant(self, e):
         return "det"
+
     def trace(self, e):
         return "tr"
+
     def dev(self, e):
         return "dev"
+
     def skew(self, e):
         return "skew"
 
     def grad(self, e):
         return "grad"
+
     def div(self, e):
         return "div"
+
     def curl(self, e):
         return "curl"
+
     def nabla_grad(self, e):
         return "nabla_grad"
+
     def nabla_div(self, e):
         return "nabla_div"
 
     def diff(self, e):
         return "diff"
 
+
 # Make this class like the ones above to use fancy math symbol labels
-class2label = {
-    "IndexSum":  "∑",
-    "Sum":       "∑",
-    "Product":   "∏",
-    "Division":  "/",
-    "Inner":     ":",
-    "Dot":       "⋅",
-    "Outer":     "⊗",
-    "Grad":      "grad",
-    "Div":       "div",
-    "NablaGrad": "∇⊗",
-    "NablaDiv":  "∇⋅",
-    "Curl":      "∇×",
-    }
+class2label = {"IndexSum": "∑",
+               "Sum": "∑",
+               "Product": "∏",
+               "Division": "/",
+               "Inner": ":",
+               "Dot": "⋅",
+               "Outer": "⊗",
+               "Grad": "grad",
+               "Div": "div",
+               "NablaGrad": "∇⊗",
+               "NablaDiv": "∇⋅",
+               "Curl": "∇×", }
+
+
 class FancyLabeller(CompactLabeller):
     pass
 
+
 def build_entities(e, nodes, edges, nodeoffset, prefix="", labeller=None):
-    # TODO: Maybe this can be cleaner written using the graph utilities.
-    # TODO: To collapse equal nodes with different objects, do not use id as key. Make this an option?
+    # TODO: Maybe this can be cleaner written using the graph
+    # utilities.
+    # TODO: To collapse equal nodes with different objects, do not use
+    # id as key. Make this an option?
 
     # Cutoff if we have handled e before
     if id(e) in nodes:
@@ -150,7 +177,7 @@ def build_entities(e, nodes, edges, nodeoffset, prefix="", labeller=None):
         labeller = ReprLabeller()
 
     # Special-case Variable instances
-    if isinstance(e, Variable): # FIXME: Is this really necessary?
+    if isinstance(e, Variable):  # FIXME: Is this really necessary?
         ops = (e._expression,)
         label = "variable %d" % e._label._count
     else:
@@ -164,7 +191,6 @@ def build_entities(e, nodes, edges, nodeoffset, prefix="", labeller=None):
     # Handle all children recursively
     n = len(ops)
     if n == 2:
-        #oplabels = ["left", "right"]
         oplabels = ["L", "R"]
     elif n > 2:
         oplabels = ["op%d" % i for i in range(n)]
@@ -178,6 +204,7 @@ def build_entities(e, nodes, edges, nodeoffset, prefix="", labeller=None):
         # Add edge between e and child node o
         edges.append((id(e), id(o), oplabels[i]))
 
+
 def format_entities(nodes, edges):
     entities = []
     for (nodename, label) in itervalues(nodes):
@@ -193,6 +220,7 @@ def format_entities(nodes, edges):
         entities.append(edge)
     return "\n".join(entities)
 
+
 integralgraphformat = """  %(node)s [label="%(label)s"]
   form_%(formname)s -> %(node)s ;
   %(node)s -> %(root)s ;
@@ -203,7 +231,9 @@ exprgraphformat = """  digraph ufl_expression
   %s
   }"""
 
-def ufl2dot(expression, formname="a", nodeoffset=0, begin=True, end=True, labeling="repr", object_names=None):
+
+def ufl2dot(expression, formname="a", nodeoffset=0, begin=True, end=True,
+            labeling="repr", object_names=None):
     if labeling == "repr":
         labeller = ReprLabeller()
     elif labeling == "compact":
@@ -215,32 +245,30 @@ def ufl2dot(expression, formname="a", nodeoffset=0, begin=True, end=True, labeli
 
         subgraphs = []
         k = 0
-        for itgs in form.integrals():
-            for itg in itgs:
-                prefix = "itg%d_" % k
-                integralkey = "%s%s" % (itg.integral_type(), itg.subdomain_id())
-
-                integrallabel = "%s %s" % (itg.integral_type().capitalize().replace("_", " "), "integral")
-                if len(itgs) > 1:
-                    integrallabel += " %s" % (itg.subdomain_id(),)
-
-                integrand = itg.integrand()
-
-                nodes = {}
-                edges = []
-
-                build_entities(integrand, nodes, edges, nodeoffset, prefix, labeller)
-                rootnode = nodes[id(integrand)][0]
-                entitylist = format_entities(nodes, edges)
-                integralnode = "%s_%s" % (formname, integralkey)
-                subgraphs.append(integralgraphformat % {
-                    'node': integralnode,
-                    'label': integrallabel,
-                    'formname': formname,
-                    'root': rootnode,
-                    'entities': entitylist,
-                    })
-                nodeoffset += len(nodes)
+        for itg in form.integrals():
+            prefix = "itg%d_" % k
+            integralkey = "%s%s" % (itg.integral_type(), itg.subdomain_id())
+
+            integrallabel = "%s %s" % (itg.integral_type().capitalize().replace("_", " "), "integral")
+            integrallabel += " %s" % (itg.subdomain_id(),)
+
+            integrand = itg.integrand()
+
+            nodes = {}
+            edges = []
+
+            build_entities(integrand, nodes, edges, nodeoffset, prefix,
+                           labeller)
+            rootnode = nodes[id(integrand)][0]
+            entitylist = format_entities(nodes, edges)
+            integralnode = "%s_%s" % (formname, integralkey)
+            subgraphs.append(integralgraphformat % {
+                'node': integralnode,
+                'label': integrallabel,
+                'formname': formname,
+                'root': rootnode,
+                'entities': entitylist, })
+            nodeoffset += len(nodes)
 
         s = ""
         if begin:
diff --git a/ufl/formatting/ufl2latex.py b/ufl/formatting/ufl2latex.py
index b2799b9..96ec8e8 100644
--- a/ufl/formatting/ufl2latex.py
+++ b/ufl/formatting/ufl2latex.py
@@ -3,7 +3,7 @@
 either converting UFL expressions to new UFL expressions or
 converting UFL expressions to other representations."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -23,13 +23,10 @@ converting UFL expressions to other representations."""
 # Modified by Anders Logg, 2008-2009.
 # Modified by Kristian B. Oelgaard, 2011
 
-from itertools import chain
-
 import ufl
-from ufl.log import error, warning
-from ufl.assertions import ufl_assert
-from ufl.utils.system import write_file, pdflatex, openpdf
+from ufl.log import error
 from ufl.permutation import compute_indices
+from ufl.algorithms.traversal import iter_expressions
 
 # All classes:
 from ufl.variable import Variable
@@ -40,17 +37,17 @@ from ufl.algebra import Sum, Product, Division, Power, Abs
 from ufl.indexsum import IndexSum
 from ufl.tensoralgebra import Transposed, Outer, Inner, Dot, Cross, Trace, Determinant, Inverse, Deviatoric, Cofactor
 from ufl.mathfunctions import Sqrt, Exp, Ln, Cos, Sin, Tan, Cosh, Sinh, Tanh, Acos, Asin, Atan, Atan2, Erf, BesselJ, BesselY, BesselI, BesselK
-from ufl.restriction import PositiveRestricted, NegativeRestricted, CellAvg, FacetAvg
+from ufl.restriction import PositiveRestricted, NegativeRestricted, CellAvg
 from ufl.differentiation import VariableDerivative, Grad, Div, Curl, NablaGrad, NablaDiv
 from ufl.conditional import EQ, NE, LE, GE, LT, GT, Conditional
 from ufl.form import Form
-from ufl.integral import Measure
 from ufl.classes import terminal_classes
 
 # Other algorithms:
 from ufl.algorithms.compute_form_data import compute_form_data
-from ufl.algorithms.formfiles import load_forms
-from ufl.algorithms.transformer import Transformer
+
+from ufl.corealg.multifunction import MultiFunction
+from ufl.corealg.map_dag import map_expr_dag
 from ufl.corealg.traversal import unique_post_traversal
 
 from ufl.formatting.graph import build_graph, partition, extract_outgoing_vertex_connections
@@ -59,8 +56,6 @@ from ufl.formatting.latextools import align, document, verbatim
 
 # TODO: Maybe this can be cleaner written using the graph utilities
 
-
-
 def _extract_variables(a):
     """Build a list of all Variable objects in a,
     which can be a Form, Integral or Expr.
@@ -77,12 +72,11 @@ def _extract_variables(a):
     return variables
 
 
-
 # --- Tools for LaTeX rendering of UFL expressions ---
 
 # TODO: Finish precedence mapping
 def build_precedence_map():
-    precedence_list = [] # TODO: Review this list very carefully!
+    precedence_list = []  # TODO: Review this list very carefully!
 
     precedence_list.append((Sum,))
     precedence_list.append((IndexSum,))
@@ -94,11 +88,14 @@ def build_precedence_map():
     precedence_list.append((Conditional,))
     precedence_list.append((LE, GT, GE, NE, EQ, LT))
 
-    precedence_list.append((Div, Grad, NablaGrad, NablaDiv, Curl, VariableDerivative,
+    precedence_list.append((Div, Grad, NablaGrad, NablaDiv, Curl,
+                            VariableDerivative,
                             Determinant, Trace, Cofactor, Inverse, Deviatoric))
     precedence_list.append((Product, Division, Cross, Dot, Outer, Inner))
     precedence_list.append((Indexed, Transposed, Power))
-    precedence_list.append((Abs, Cos, Cosh, Exp, Ln, Sin, Sinh, Sqrt, Tan, Tanh, Acos, Asin, Atan, Atan2, Erf, BesselJ, BesselY, BesselI, BesselK))
+    precedence_list.append((Abs, Cos, Cosh, Exp, Ln, Sin, Sinh, Sqrt, Tan,
+                            Tanh, Acos, Asin, Atan, Atan2, Erf, BesselJ,
+                            BesselY, BesselI, BesselK))
     precedence_list.append((Variable,))
     precedence_list.append(terminal_classes)
 
@@ -110,12 +107,14 @@ def build_precedence_map():
         k += 1
     return precedence_map
 
+
 # Utility for parentesizing string
-def par(s, condition=True): # TODO: Finish precedence handling by adding condition argument to calls to this function!
+def par(s, condition=True):  # TODO: Finish precedence handling by adding condition argument to calls to this function!
     if condition:
         return r"\left(%s\right)" % s
     return str(s)
 
+
 def format_index(ii):
     if isinstance(ii, FixedIndex):
         s = "%d" % ii._value
@@ -125,21 +124,25 @@ def format_index(ii):
         error("Invalid index type %s." % type(ii))
     return s
 
+
 def format_multi_index(ii, formatstring="%s"):
     return "".join(formatstring % format_index(i) for i in ii)
 
+
 def bfname(i, p):
-    s = "" if p is None else (",%d"%(p,))
+    s = "" if p is None else (",%d" % (p,))
     return "{v_h^{%d%s}}" % (i, s)
 
+
 def cfname(i):
     return "{w_h^%d}" % i
 
+
 # TODO: Handle line wrapping
 # TODO: Handle ListTensors of rank > 1 correctly
-class Expression2LatexHandler(Transformer):
+class Expression2LatexHandler(MultiFunction):
     def __init__(self, argument_names=None, coefficient_names=None):
-        Transformer.__init__(self)
+        MultiFunction.__init__(self)
         self.argument_names = argument_names
         self.coefficient_names = coefficient_names
 
@@ -163,13 +166,15 @@ class Expression2LatexHandler(Transformer):
         return r"{\mathbf n}"
 
     def argument(self, o):
-        # Using ^ for argument numbering and _ for indexing since indexing is more common than exponentiation
+        # Using ^ for argument numbering and _ for indexing since
+        # indexing is more common than exponentiation
         if self.argument_names is None:
             return bfname(o.number(), o.part())
         return self.argument_names[(o.number(), o.part())]
 
     def coefficient(self, o):
-        # Using ^ for coefficient numbering and _ for indexing since indexing is more common than exponentiation
+        # Using ^ for coefficient numbering and _ for indexing since
+        # indexing is more common than exponentiation
         if self.coefficient_names is None:
             return cfname(o.count())
         return self.coefficient_names[o.count()]
@@ -207,14 +212,14 @@ class Expression2LatexHandler(Transformer):
         return "{%s}_{%s}" % (par(a), b)
 
     def variable_derivative(self, o, f, v):
-        nom   = r"\partial%s" % par(f)
+        nom = r"\partial%s" % par(f)
         denom = r"\partial%s" % par(v)
         return r"\frac{%s}{%s}" % (nom, denom)
 
     def coefficient_derivative(self, o, f, w, v):
-        nom   = r"\partial%s" % par(f)
+        nom = r"\partial%s" % par(f)
         denom = r"\partial%s" % par(w)
-        return r"\frac{%s}{%s}[%s]" % (nom, denom, v) # TODO: Fix this syntax...
+        return r"\frac{%s}{%s}[%s]" % (nom, denom, v)  # TODO: Fix this syntax...
 
     def grad(self, o, f):
         return r"\mathbf{grad}{%s}" % par(f)
@@ -301,25 +306,25 @@ class Expression2LatexHandler(Transformer):
         return r"{%s}\times{%s}" % (par(a), par(b))
 
     def trace(self, o, A):
-        return "tr{%s}" % par(A) # TODO: Get built-in function syntax like \sin for this
+        return "tr{%s}" % par(A)  # TODO: Get built-in function syntax like \sin for this
 
     def determinant(self, o, A):
-        return "det{%s}" % par(A) # TODO: Get built-in function syntax like \sin for this
+        return "det{%s}" % par(A)  # TODO: Get built-in function syntax like \sin for this
 
     def inverse(self, o, A):
         return "{%s}^{-1}" % par(A)
 
     def deviatoric(self, o, A):
-        return "dev{%s}" % par(A) # TODO: Get built-in function syntax like \sin for this
+        return "dev{%s}" % par(A)  # TODO: Get built-in function syntax like \sin for this
 
     def cofactor(self, o, A):
-        return "cofac{%s}" % par(A) # TODO: Get built-in function syntax like \sin for this
+        return "cofac{%s}" % par(A)  # TODO: Get built-in function syntax like \sin for this
 
     def skew(self, o, A):
-        return "skew{%s}" % par(A) # TODO: Get built-in function syntax like \sin for this
+        return "skew{%s}" % par(A)  # TODO: Get built-in function syntax like \sin for this
 
     def sym(self, o, A):
-        return "sym{%s}" % par(A) # TODO: Get built-in function syntax like \sin for this
+        return "sym{%s}" % par(A)  # TODO: Get built-in function syntax like \sin for this
 
     def list_tensor(self, o):
         shape = o.ufl_shape
@@ -330,7 +335,7 @@ class Expression2LatexHandler(Transformer):
             rows = []
             for row in o.ufl_operands:
                 cols = (self.visit(op) for op in row.ufl_operands)
-                rows.append( " & \n ".join(cols) )
+                rows.append(" & \n ".join(cols))
             l = " \\\\ \n ".join(rows)
         else:
             error("TODO: LaTeX handler for list tensor of rank 3 or higher not implemented!")
@@ -392,9 +397,11 @@ class Expression2LatexHandler(Transformer):
     def expr(self, o):
         error("Missing handler for type %s" % str(type(o)))
 
+
 def expression2latex(expression, argument_names=None, coefficient_names=None):
-    visitor = Expression2LatexHandler(argument_names, coefficient_names)
-    return visitor.visit(expression)
+    rules = Expression2LatexHandler(argument_names, coefficient_names)
+    return map_expr_dag(rules, expression)
+
 
 def element2latex(element):
     e = str(element)
@@ -403,19 +410,20 @@ def element2latex(element):
     e = "fixme"
     return r"{\mbox{%s}}" % e
 
-domain_strings = { "cell": r"\Omega",
-                   "exterior_facet": r"\Gamma^{ext}",
-                   "exterior_facet_bottom": r"\Gamma_{bottom}^{ext}",
-                   "exterior_facet_top": r"\Gamma_{top}^{ext}",
-                   "exterior_facet_vert": r"\Gamma_{vert}^{ext}",
-                   "interior_facet": r"\Gamma^{int}",
-                   "interior_facet_horiz": r"\Gamma_{horiz}^{int}",
-                   "interior_facet_vert": r"\Gamma_{vert}^{int}",
-                   "vertex": r"\Gamma^{vertex}",
-                   "custom": r"\Gamma^{custom}",
-                 }
+
+domain_strings = {"cell": r"\Omega",
+                  "exterior_facet": r"\Gamma^{ext}",
+                  "exterior_facet_bottom": r"\Gamma_{bottom}^{ext}",
+                  "exterior_facet_top": r"\Gamma_{top}^{ext}",
+                  "exterior_facet_vert": r"\Gamma_{vert}^{ext}",
+                  "interior_facet": r"\Gamma^{int}",
+                  "interior_facet_horiz": r"\Gamma_{horiz}^{int}",
+                  "interior_facet_vert": r"\Gamma_{vert}^{int}",
+                  "vertex": r"\Gamma^{vertex}",
+                  "custom": r"\Gamma^{custom}", }
 default_domain_string = "d(?)"
 
+
 def form2latex(form, formdata):
 
     formname = formdata.name
@@ -448,13 +456,14 @@ def form2latex(form, formdata):
     for f in formdata.original_arguments:
         i = f.number()
         p = f.part()
-        lines.append("%s = %s \\in V_h^{%d} " % (argument_names[(i, p)], bfname(i, p), i)) # FIXME: Handle part in V_h
+        lines.append("%s = %s \\in V_h^{%d} " % (argument_names[(i, p)], bfname(i, p), i))  # FIXME: Handle part in V_h
     for i, f in enumerate(formdata.original_coefficients):
         lines.append("%s = %s \\in W_h^{%d} " % (coefficient_names[i], cfname(i), i))
     if lines:
         sections.append(("Form arguments", align(lines)))
 
-    # TODO: Wrap ListTensors, ComponentTensor and Conditionals in expression as variables before transformation
+    # TODO: Wrap ListTensors, ComponentTensor and Conditionals in
+    # expression as variables before transformation
 
     # Define variables
     handled_variables = set()
@@ -466,7 +475,9 @@ def form2latex(form, formdata):
             l = v._label
             if l not in handled_variables:
                 handled_variables.add(l)
-                exprlatex = expression2latex(v._expression, formdata.argument_names, formdata.coefficient_names)
+                exprlatex = expression2latex(v._expression,
+                                             formdata.argument_names,
+                                             formdata.coefficient_names)
                 lines.append(("s_{%d}" % l._count, "= %s" % exprlatex))
     if lines:
         sections.append(("Variables", align(lines)))
@@ -482,13 +493,16 @@ def form2latex(form, formdata):
     a = signature
     p = ""
     for itg in integrals:
-        # TODO: Get list of expression strings instead of single expression!
-        integrand_string = expression2latex(itg.integrand(), formdata.argument_names, formdata.coefficient_names)
+        # TODO: Get list of expression strings instead of single
+        # expression!
+        integrand_string = expression2latex(itg.integrand(),
+                                            formdata.argument_names,
+                                            formdata.coefficient_names)
 
         integral_type = itg.integral_type()
         dstr = domain_strings[integral_type]
 
-        domain = itg.ufl_domain()
+        # domain = itg.ufl_domain()
         # TODO: Render domain description
 
         subdomain_id = itg.subdomain_id()
@@ -512,6 +526,7 @@ def form2latex(form, formdata):
 
     return sections
 
+
 def ufl2latex(expression):
     "Generate LaTeX code for a UFL expression or form (wrapper for form2latex and expression2latex)."
     if isinstance(expression, Form):
@@ -521,13 +536,14 @@ def ufl2latex(expression):
     else:
         return expression2latex(expression)
 
+
 # --- LaTeX rendering of composite UFL objects ---
 
 def deps2latex(deps):
     return "Dependencies: ${ %s }$." % ", ".join(sorted(deps))
 
+
 def dependency_sorting(deplist, rank):
-    #print "deplist = ", deplist
 
     def split(deps, state):
         left = []
@@ -544,7 +560,6 @@ def dependency_sorting(deplist, rank):
     left = deplist
 
     # --- Initialization time
-    #state.remove("x")
     precompute, left = split(left, state)
     deplistlist.append(precompute)
 
@@ -554,7 +569,7 @@ def dependency_sorting(deplist, rank):
 
     # Permutations of 0/1 dependence of arguments
     indices = compute_indices((2,)*rank)
-    for bfs in indices[1:]: # skip (0,...,0), already handled that
+    for bfs in indices[1:]:  # skip (0,...,0), already handled that
         for i, bf in reversed(enumerate(bfs)):
             n = "v%d" % i
             if bf:
@@ -578,7 +593,7 @@ def dependency_sorting(deplist, rank):
     deplistlist.append(runtime_quad)
 
     indices = compute_indices((2,)*rank)
-    for bfs in indices[1:]: # skip (0,...,0), already handled that
+    for bfs in indices[1:]:  # skip (0,...,0), already handled that
         for i, bf in reversed(enumerate(bfs)):
             n = "v%d" % i
             if bf:
@@ -589,27 +604,21 @@ def dependency_sorting(deplist, rank):
         next, left = split(left, state)
         deplistlist.append(next)
 
-    ufl_assert(not left, "Shouldn't have anything left!")
-
-    #print
-    #print "Created deplistlist:"
-    #for deps in deplistlist:
-    #    print
-    #    print "--- New stage:"
-    #    print "\n".join(map(str, deps))
-    #print
+    if left:
+        error("Shouldn't have anything left!")
 
     return deplistlist
 
+
 def code2latex(G, partitions, formdata):
     "TODO: Document me"
     bfn = formdata.argument_names
-    cfn = formdata.coefficient_names
 
     V, E = G
     Vout = extract_outgoing_vertex_connections(G)
 
-    # Sort dependency sets in a sensible way (preclude to a good quadrature code generator)
+    # Sort dependency sets in a sensible way (preclude to a good
+    # quadrature code generator)
     deplistlist = dependency_sorting(list(partitions.keys()), len(bfn))
 
     def format_v(i):
@@ -617,7 +626,6 @@ def code2latex(G, partitions, formdata):
 
     pieces = []
     for deplist in deplistlist:
-        #pieces.append("\n\n(Debugging: getting next list of dependencies)")
         for dep in deplist:
             lines = []
             for iv in partitions[dep]:
@@ -627,7 +635,7 @@ def code2latex(G, partitions, formdata):
                 args = ", ".join(format_v(i) for i in vout)
                 if args:
                     el = r"{\mbox{%s}}(%s)" % (v._ufl_class_.__name__, args)
-                else: # terminal
+                else:  # terminal
                     el = r"{\mbox{%s}}" % (repr(v),)
                 lines.append((vl, "= " + el))
             pieces.extend(("\n", deps2latex(dep), align(lines)))
@@ -637,18 +645,22 @@ def code2latex(G, partitions, formdata):
     pieces.append("\n")
     pieces.append("Variable representing integrand: %s" % vl)
 
-    # Could also return list of (title, body) parts for subsections if wanted
+    # Could also return list of (title, body) parts for subsections if
+    # wanted
     body = "\n".join(pieces)
     return body
 
+
 def integrand2code(integrand, formdata):
     G = build_graph(integrand)
     partitions, keys = partition(G)
     return G, partitions
 
-def formdata2latex(formdata): # TODO: Format better
+
+def formdata2latex(formdata):  # TODO: Format better
     return verbatim(str(formdata))
 
+
 def form2code2latex(formdata):
     # Render introductory sections
     title = "Form data"
@@ -657,7 +669,8 @@ def form2code2latex(formdata):
 
     # Render each integral as a separate section
     for itg in formdata.form.integrals():
-        title = "%s integral over domain %d" % (itg.integral_type(), itg.subdomain_id())
+        title = "%s integral over domain %d" % (itg.integral_type(),
+                                                itg.subdomain_id())
 
         G, partitions = integrand2code(itg.integrand(), formdata)
 
@@ -667,6 +680,7 @@ def form2code2latex(formdata):
 
     return sections
 
+
 # --- Creating complete documents ---
 
 def forms2latexdocument(forms, uflfilename, compile=False):
@@ -695,25 +709,6 @@ def forms2latexdocument(forms, uflfilename, compile=False):
         title = "Forms " + suffix
     return document(title, sections)
 
-# --- File operations ---
-
-def ufl2tex(uflfilename, latexfilename, compile=False):
-    "Compile a .tex file from a .ufl file."
-    forms = load_forms(uflfilename)
-    latex = forms2latexdocument(forms, uflfilename, compile)
-    write_file(latexfilename, latex)
-
-def tex2pdf(latexfilename, pdffilename):
-    "Compile a .pdf file from a .tex file."
-    pdflatex(latexfilename, pdffilename)
-    openpdf(pdffilename)
-
-def ufl2pdf(uflfilename, latexfilename, pdffilename, compile=False):
-    "Compile a .pdf file from a .ufl file."
-    ufl2tex(uflfilename, latexfilename, compile)
-    tex2pdf(latexfilename, pdffilename)
-
-
 
 """# Code from uflacs:
 
diff --git a/ufl/formoperators.py b/ufl/formoperators.py
index 150ad95..44601ef 100644
--- a/ufl/formoperators.py
+++ b/ufl/formoperators.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Various high level ways to transform a complete Form into a new Form."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,15 +19,15 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2009
+# Modified by Massimiliano Leoni, 2016
 
 from six import iteritems
 from six.moves import zip
 from six.moves import xrange as range
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.form import Form, as_form
-from ufl.core.expr import Expr
+from ufl.core.expr import Expr, ufl_err_str
 from ufl.split_functions import split
 from ufl.exprcontainers import ExprList, ExprMapping
 from ufl.variable import Variable
@@ -43,18 +43,15 @@ from ufl.sorting import sorted_expr
 from ufl.functionspace import FunctionSpace
 
 # An exception to the rule that ufl.* does not depend on ufl.algorithms.* ...
-from ufl.algorithms import compute_form_adjoint, \
-                           compute_form_action, \
-                           compute_energy_norm, \
-                           compute_form_lhs, \
-                           compute_form_rhs, \
-                           compute_form_functional, \
-                           expand_derivatives, \
-                           extract_arguments, \
-                           FormSplitter
+from ufl.algorithms import compute_form_adjoint, compute_form_action
+from ufl.algorithms import compute_energy_norm
+from ufl.algorithms import compute_form_lhs, compute_form_rhs, compute_form_functional
+from ufl.algorithms import expand_derivatives, extract_arguments
+from ufl.algorithms import FormSplitter
 
 # Part of the external interface
-from ufl.algorithms import replace
+from ufl.algorithms import replace  # noqa
+
 
 def block_split(form, ix, iy=0):
     """UFL form operator:
@@ -69,12 +66,13 @@ def block_split(form, ix, iy=0):
     fs = FormSplitter()
     return fs.split(form, ix, iy)
 
+
 def lhs(form):
     """UFL form operator:
     Given a combined bilinear and linear form,
     extract the left hand side (bilinear form part).
 
-    Example:
+    Example::
 
         a = u*v*dx + f*v*dx
         a = lhs(a) -> u*v*dx
@@ -83,12 +81,13 @@ def lhs(form):
     form = expand_derivatives(form)
     return compute_form_lhs(form)
 
+
 def rhs(form):
     """UFL form operator:
     Given a combined bilinear and linear form,
     extract the right hand side (negated linear form part).
 
-    Example:
+    Example::
 
         a = u*v*dx + f*v*dx
         L = rhs(a) -> -f*v*dx
@@ -97,16 +96,20 @@ def rhs(form):
     form = expand_derivatives(form)
     return compute_form_rhs(form)
 
+
 def system(form):
-    "UFL form operator: Split a form into the left hand side and right hand side, see lhs and rhs."
+    """UFL form operator: Split a form into the left hand side and right hand
+    side, see ``lhs`` and ``rhs``."""
     return lhs(form), rhs(form)
 
-def functional(form): # TODO: Does this make sense for anything other than testing?
+
+def functional(form):  # TODO: Does this make sense for anything other than testing?
     "UFL form operator: Extract the functional part of form."
     form = as_form(form)
     form = expand_derivatives(form)
     return compute_form_functional(form)
 
+
 def action(form, coefficient=None):
     """UFL form operator:
     Given a bilinear form, return a linear form
@@ -117,35 +120,40 @@ def action(form, coefficient=None):
     form = expand_derivatives(form)
     return compute_form_action(form, coefficient)
 
+
 def energy_norm(form, coefficient=None):
     """UFL form operator:
-    Given a bilinear form a and a coefficient f,
-    return the functional a(f,f)."""
+    Given a bilinear form *a* and a coefficient *f*,
+    return the functional :math:`a(f,f)`."""
     form = as_form(form)
     form = expand_derivatives(form)
     return compute_energy_norm(form, coefficient)
 
+
 def adjoint(form, reordered_arguments=None):
     """UFL form operator:
     Given a combined bilinear form, compute the adjoint form by
     changing the ordering (count) of the test and trial functions.
 
-    By default, new Argument objects will be created with
+    By default, new ``Argument`` objects will be created with
     opposite ordering. However, if the adjoint form is to
     be added to other forms later, their arguments must match.
-    In that case, the user must provide a tuple reordered_arguments=(u2,v2).
+    In that case, the user must provide a tuple *reordered_arguments*=(u2,v2).
     """
     form = as_form(form)
     form = expand_derivatives(form)
     return compute_form_adjoint(form, reordered_arguments)
 
+
 def zero_lists(shape):
-    ufl_assert(len(shape) > 0, "Invalid shape.")
-    if len(shape) == 1:
+    if len(shape) == 0:
+        error("Invalid shape.")
+    elif len(shape) == 1:
         return [0]*shape[0]
     else:
         return [zero_lists(shape[1:]) for i in range(shape[0])]
 
+
 def set_list_item(li, i, v):
     # Get to the innermost list
     if len(i) > 1:
@@ -154,6 +162,7 @@ def set_list_item(li, i, v):
     # Set item in innermost list
     li[i[-1]] = v
 
+
 def _handle_derivative_arguments(form, coefficient, argument):
     # Wrap single coefficient in tuple for uniform treatment below
     if isinstance(coefficient, (list, tuple, ListTensor)):
@@ -166,19 +175,23 @@ def _handle_derivative_arguments(form, coefficient, argument):
         if not all(isinstance(c, Coefficient) for c in coefficients):
             error("Can only create arguments automatically for non-indexed coefficients.")
 
-        # Get existing arguments from form and position the new one with the next argument number
+        # Get existing arguments from form and position the new one
+        # with the next argument number
         if isinstance(form, Form):
             form_arguments = form.arguments()
         else:
-            # To handle derivative(expression), which is at least used in tests. Remove?
+            # To handle derivative(expression), which is at least used
+            # in tests. Remove?
             form_arguments = extract_arguments(form)
 
         numbers = sorted(set(arg.number() for arg in form_arguments))
         number = max(numbers + [-1]) + 1
 
-        # Don't know what to do with parts, let the user sort it out in that case
+        # Don't know what to do with parts, let the user sort it out
+        # in that case
         parts = set(arg.part() for arg in form_arguments)
-        ufl_assert(len(parts - {None}) == 0, "Not expecting parts here, provide your own arguments.")
+        if len(parts - {None}) != 0:
+            error("Not expecting parts here, provide your own arguments.")
         part = None
 
         # Create argument and split it if in a mixed space
@@ -210,15 +223,18 @@ def _handle_derivative_arguments(form, coefficient, argument):
     # Build mapping from coefficient to argument
     m = {}
     for (c, a) in zip(coefficients, arguments):
-        ufl_assert(c.ufl_shape == a.ufl_shape, "Coefficient and argument shapes do not match!")
+        if c.ufl_shape != a.ufl_shape:
+            error("Coefficient and argument shapes do not match!")
         if isinstance(c, Coefficient):
             m[c] = a
         else:
-            ufl_assert(isinstance(c, Indexed), "Invalid coefficient type for %s" % repr(c))
+            if not isinstance(c, Indexed):
+                error("Invalid coefficient type for %s" % ufl_err_str(c))
             f, i = c.ufl_operands
-            ufl_assert(isinstance(f, Coefficient), "Expecting an indexed coefficient, not %s" % repr(f))
-            ufl_assert(isinstance(i, MultiIndex) and all(isinstance(j, FixedIndex) for j in i),
-                       "Expecting one or more fixed indices, not %s" % repr(i))
+            if not isinstance(f, Coefficient):
+                error("Expecting an indexed coefficient, not %s" % ufl_err_str(f))
+            if not (isinstance(i, MultiIndex) and all(isinstance(j, FixedIndex) for j in i)):
+                error("Expecting one or more fixed indices, not %s" % ufl_err_str(i))
             i = tuple(int(j) for j in i)
             if f not in m:
                 m[f] = {}
@@ -238,30 +254,33 @@ def _handle_derivative_arguments(form, coefficient, argument):
     arguments = ExprList(*[item[1] for item in items])
     return coefficients, arguments
 
+
 def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
     """UFL form operator:
-    Compute the Gateaux derivative of form w.r.t. coefficient in direction of argument.
+    Compute the Gateaux derivative of *form* w.r.t. *coefficient* in direction
+    of *argument*.
 
-    If the argument is omitted, a new Argument is created
+    If the argument is omitted, a new ``Argument`` is created
     in the same space as the coefficient, with argument number
     one higher than the highest one in the form.
 
-    The resulting form has one additional Argument
+    The resulting form has one additional ``Argument``
     in the same finite element space as the coefficient.
 
-    A tuple of Coefficients may be provided in place of
-    a single Coefficient, in which case the new Argument
-    argument is based on a MixedElement created from this tuple.
+    A tuple of ``Coefficient`` s may be provided in place of
+    a single ``Coefficient``, in which case the new ``Argument``
+    argument is based on a ``MixedElement`` created from this tuple.
 
-    An indexed Coefficient from a mixed space may be provided,
+    An indexed ``Coefficient`` from a mixed space may be provided,
     in which case the argument should be in the corresponding
     subspace of the coefficient space.
 
-    If provided, coefficient_derivatives should be a mapping from
-    Coefficient instances to their derivatives w.r.t. 'coefficient'.
+    If provided, *coefficient_derivatives* should be a mapping from
+    ``Coefficient`` instances to their derivatives w.r.t. *coefficient*.
     """
 
-    coefficients, arguments = _handle_derivative_arguments(form, coefficient, argument)
+    coefficients, arguments = _handle_derivative_arguments(form, coefficient,
+                                                           argument)
 
     if coefficient_derivatives is None:
         coefficient_derivatives = ExprMapping()
@@ -287,57 +306,69 @@ def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
 
     error("Invalid argument type %s." % str(type(form)))
 
+
 def sensitivity_rhs(a, u, L, v):
     """UFL form operator:
     Compute the right hand side for a sensitivity calculation system.
 
     The derivation behind this computation is as follows.
-    Assume a, L to be bilinear and linear forms
+    Assume *a*, *L* to be bilinear and linear forms
     corresponding to the assembled linear system
 
+    .. math::
+
         Ax = b.
 
-    Where x is the vector of the discrete function corresponding to u.
-    Let v be some scalar variable this equation depends on.
+    Where *x* is the vector of the discrete function corresponding to *u*.
+    Let *v* be some scalar variable this equation depends on.
     Then we can write
 
-        0 = d/dv[Ax-b] = dA/dv x + A dx/dv - db/dv,
-        A dx/dv = db/dv - dA/dv x,
+    .. math::
+        0 = \\frac{d}{dv}(Ax-b) = \\frac{dA}{dv} x + A \\frac{dx}{dv} -
+        \\frac{db}{dv},
+
+        A \\frac{dx}{dv} = \\frac{db}{dv} - \\frac{dA}{dv} x,
 
-    and solve this system for dx/dv, using the same bilinear form a
-    and matrix A from the original system.
+    and solve this system for :math:`\\frac{dx}{dv}`, using the same bilinear
+    form *a* and matrix *A* from the original system.
     Assume the forms are written
+    ::
 
         v = variable(v_expression)
         L = IL(v)*dx
         a = Ia(v)*dx
 
-    where IL and Ia are integrand expressions.
-    Define a Coefficient u representing the solution
-    to the equations. Then we can compute db/dv
-    and dA/dv from the forms
+    where ``IL`` and ``Ia`` are integrand expressions.
+    Define a ``Coefficient u`` representing the solution
+    to the equations. Then we can compute :math:`\\frac{db}{dv}`
+    and :math:`\\frac{dA}{dv}` from the forms
+    ::
 
         da = diff(a, v)
         dL = diff(L, v)
 
-    and the action of da on u by
+    and the action of ``da`` on ``u`` by
+    ::
 
         dau = action(da, u)
 
     In total, we can build the right hand side of the system
-    to compute du/dv with the single line
+    to compute :math:`\\frac{du}{dv}` with the single line
+    ::
 
         dL = diff(L, v) - action(diff(a, v), u)
 
-    or, using this function
+    or, using this function,
+    ::
 
         dL = sensitivity_rhs(a, u, L, v)
     """
-    msg = "Expecting (a, u, L, v), (bilinear form, function, linear form and scalar variable)."
-    ufl_assert(isinstance(a, Form), msg)
-    ufl_assert(isinstance(u, Coefficient), msg)
-    ufl_assert(isinstance(L, Form), msg)
-    ufl_assert(isinstance(v, Variable), msg)
-    ufl_assert(is_true_ufl_scalar(v), "Expecting scalar variable.")
+    if not (isinstance(a, Form) and
+            isinstance(u, Coefficient) and
+            isinstance(L, Form) and
+            isinstance(v, Variable)):
+        error("Expecting (a, u, L, v), (bilinear form, function, linear form and scalar variable).")
+    if not is_true_ufl_scalar(v):
+        error("Expecting scalar variable.")
     from ufl.operators import diff
     return diff(L, v) - action(diff(a, v), u)
diff --git a/ufl/functionspace.py b/ufl/functionspace.py
index 64b2cde..94c4816 100644
--- a/ufl/functionspace.py
+++ b/ufl/functionspace.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Types for representing function spaces."
 
-# Copyright (C) 2015-2015 Martin Sandve Alnæs
+# Copyright (C) 2015-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -17,32 +17,30 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016
 
-#from ufl.core.terminal import Terminal
-#from ufl.corealg.traversal import traverse_unique_terminals
-#from ufl.utils.formatting import istr
-#from ufl.utils.dicts import EmptyDict
-#from ufl.log import warning, error, deprecate
-#from ufl.assertions import ufl_assert
-#from ufl.protocols import id_or_none
-#from ufl.cell import as_cell, AbstractCell, Cell, ProductCell
-
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 from ufl.core.ufl_type import attach_operators_from_hash_data
 from ufl.domain import join_domains
 from ufl.finiteelement import MixedElement
 
 # Export list for ufl.classes
-__all_classes__ = [
+__all_classes__ = as_native_strings([
     "AbstractFunctionSpace",
     "FunctionSpace",
     "MixedFunctionSpace",
     "TensorProductFunctionSpace",
-    ]
+])
+
 
 class AbstractFunctionSpace(object):
     def ufl_sub_spaces(self):
         raise NotImplementedError("Missing implementation of IFunctionSpace.ufl_sub_spaces in %s." % self.__class__.__name__)
 
+
 @attach_operators_from_hash_data
 class FunctionSpace(AbstractFunctionSpace):
     def __init__(self, domain, element):
@@ -51,31 +49,55 @@ class FunctionSpace(AbstractFunctionSpace):
         self._ufl_element = element
 
     def ufl_sub_spaces(self):
+        "Return ufl sub spaces."
         return ()
 
     def ufl_domain(self):
+        "Return ufl domain."
         return self._ufl_domain
 
     def ufl_element(self):
+        "Return ufl element."
         return self._ufl_element
 
     def ufl_domains(self):
-        return (self.ufl_domain(),)
+        "Return ufl domains."
+        domain = self.ufl_domain()
+        if domain is None:
+            return ()
+        else:
+            return (domain,)
 
     def _ufl_hash_data_(self):
-        edata = repr(self.ufl_element())
         domain = self.ufl_domain()
-        ddata = None if domain is None else domain._ufl_hash_data_()
+        element = self.ufl_element()
+        if domain is None:
+            ddata = None
+        else:
+            ddata = domain._ufl_hash_data_()
+        if element is None:
+            edata = None
+        else:
+            edata = element._ufl_hash_data_()
         return ("FunctionSpace", ddata, edata)
 
     def _ufl_signature_data_(self, renumbering):
-        edata = repr(self.ufl_element())
         domain = self.ufl_domain()
-        ddata = None if domain is None else domain._ufl_signature_data_(renumbering)
+        element = self.ufl_element()
+        if domain is None:
+            ddata = None
+        else:
+            ddata = domain._ufl_signature_data_(renumbering)
+        if element is None:
+            edata = None
+        else:
+            edata = element._ufl_signature_data_()
         return ("FunctionSpace", ddata, edata)
 
     def __repr__(self):
-        return "FunctionSpace(%r, %r)" % (self._ufl_domain, self._ufl_element)
+        r = "FunctionSpace(%s, %s)" % (repr(self._ufl_domain), repr(self._ufl_element))
+        return as_native_str(r)
+
 
 @attach_operators_from_hash_data
 class MixedFunctionSpace(AbstractFunctionSpace):
@@ -85,18 +107,22 @@ class MixedFunctionSpace(AbstractFunctionSpace):
         self._ufl_element = MixedElement(*[fs.ufl_element() for fs in function_spaces])
 
     def ufl_sub_spaces(self):
+        "Return ufl sub spaces."
         return self._ufl_function_spaces
 
     def ufl_element(self):
+        "Return ufl element."
         return self._ufl_element
 
     def ufl_domains(self):
+        "Return ufl domains."
         domainlist = []
         for s in self._ufl_function_spaces:
             domainlist.extend(s.ufl_domains())
         return join_domains(domainlist)
 
     def ufl_domain(self):
+        "Return ufl domain."
         domains = self.ufl_domains()
         if len(domains) == 1:
             return domains[0]
@@ -112,7 +138,9 @@ class MixedFunctionSpace(AbstractFunctionSpace):
         return ("MixedFunctionSpace",) + tuple(V._ufl_signature_data_(renumbering) for V in self.ufl_sub_spaces())
 
     def __repr__(self):
-        return "MixedFunctionSpace(*%r)" % (self._ufl_function_spaces,)
+        r = "MixedFunctionSpace(*%s)" % repr(self._ufl_function_spaces)
+        return as_native_str(r)
+
 
 @attach_operators_from_hash_data
 class TensorProductFunctionSpace(AbstractFunctionSpace):
@@ -130,4 +158,5 @@ class TensorProductFunctionSpace(AbstractFunctionSpace):
         return ("TensorProductFunctionSpace",) + tuple(V._ufl_signature_data_(renumbering) for V in self.ufl_sub_spaces())
 
     def __repr__(self):
-        return "TensorProductFunctionSpace(*%r)" % (self._ufl_function_spaces,)
+        r = "TensorProductFunctionSpace(*%s)" % repr(self._ufl_function_spaces)
+        return as_native_str(r)
diff --git a/ufl/geometry.py b/ufl/geometry.py
index d9ed91c..7199233 100644
--- a/ufl/geometry.py
+++ b/ufl/geometry.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Types for representing symbolic expressions for geometric quantities."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,9 +21,11 @@
 # Modified by Anders Logg, 2009.
 # Modified by Kristian B. Oelgaard, 2009
 # Modified by Marie E. Rognes 2012
+# Modified by Massimiliano Leoni, 2016
 
-from ufl.log import warning, error, deprecate
-from ufl.assertions import ufl_assert
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 from ufl.core.ufl_type import ufl_type
 from ufl.core.terminal import Terminal
 from ufl.domain import as_domain
@@ -95,7 +97,8 @@ Xf = CFK * (X - X0f)
 
 @ufl_type(is_abstract=True)
 class GeometricQuantity(Terminal):
-    __slots__ = ("_domain",)
+    __slots__ = as_native_strings(("_domain",))
+
     def __init__(self, domain):
         Terminal.__init__(self)
         self._domain = as_domain(domain)
@@ -105,10 +108,12 @@ class GeometricQuantity(Terminal):
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell (or over each facet for facet quantities)."
-        # NB! Geometric quantities are piecewise constant by default. Override if needed.
+        # NB! Geometric quantities are piecewise constant by
+        # default. Override if needed.
         return True
 
-    # NB! Geometric quantities are scalar by default. Override if needed.
+    # NB! Geometric quantities are scalar by default. Override if
+    # needed.
     ufl_shape = ()
 
     def _ufl_signature_data_(self, renumbering):
@@ -119,7 +124,8 @@ class GeometricQuantity(Terminal):
         return self._ufl_class_.name
 
     def __repr__(self):
-        return "%s(%r)" % (self._ufl_class_.__name__, self._domain)
+        r = "%s(%s)" % (self._ufl_class_.__name__, repr(self._domain))
+        return as_native_str(r)
 
     def _ufl_compute_hash_(self):
         return hash((type(self).__name__,) + self._domain._ufl_hash_data_())
@@ -127,13 +133,15 @@ class GeometricQuantity(Terminal):
     def __eq__(self, other):
         return isinstance(other, self._ufl_class_) and other._domain == self._domain
 
+
 @ufl_type(is_abstract=True)
 class GeometricCellQuantity(GeometricQuantity):
-    __slots__ = []
+    __slots__ = ()
+
 
 @ufl_type(is_abstract=True)
 class GeometricFacetQuantity(GeometricQuantity):
-    __slots__ = []
+    __slots__ = ()
 
 
 # --- Coordinate represented in different coordinate systems
@@ -153,6 +161,8 @@ class SpatialCoordinate(GeometricCellQuantity):
 
     @property
     def ufl_shape(self):
+        """Return the number of coordinates defined (i.e. the geometric dimension
+        of the domain)."""
         g = self._domain.geometric_dimension()
         return (g,)
 
@@ -163,6 +173,7 @@ class SpatialCoordinate(GeometricCellQuantity):
         return t == 0
 
     def evaluate(self, x, mapping, component, index_values):
+        "Return the value of the coordinate."
         if component == ():
             if isinstance(x, (tuple, list)):
                 return float(x[0])
@@ -171,6 +182,7 @@ class SpatialCoordinate(GeometricCellQuantity):
         else:
             return float(x[component[0]])
 
+
 @ufl_type()
 class CellCoordinate(GeometricCellQuantity):
     """UFL geometry representation: The coordinate in a reference cell.
@@ -195,6 +207,7 @@ class CellCoordinate(GeometricCellQuantity):
         t = self._domain.topological_dimension()
         return t == 0
 
+
 @ufl_type()
 class FacetCoordinate(GeometricFacetQuantity):
     """UFL geometry representation: The coordinate in a reference cell of a facet.
@@ -211,7 +224,8 @@ class FacetCoordinate(GeometricFacetQuantity):
     def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 1, "FacetCoordinate is only defined for topological dimensions > 1.")
+        if t < 2:
+            error("FacetCoordinate is only defined for topological dimensions >= 2.")
 
     @property
     def ufl_shape(self):
@@ -220,7 +234,8 @@ class FacetCoordinate(GeometricFacetQuantity):
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # Only case this is true is if the domain is an interval cell (with a vertex facet).
+        # Only case this is true is if the domain is an interval cell
+        # (with a vertex facet).
         t = self._domain.topological_dimension()
         return t <= 1
 
@@ -241,6 +256,7 @@ class CellOrigin(GeometricCellQuantity):
     def is_cellwise_constant(self):
         return True
 
+
 @ufl_type()
 class FacetOrigin(GeometricFacetQuantity):
     """UFL geometry representation: The spatial coordinate corresponding to origin of a reference facet."""
@@ -252,6 +268,7 @@ class FacetOrigin(GeometricFacetQuantity):
         g = self._domain.geometric_dimension()
         return (g,)
 
+
 @ufl_type()
 class CellFacetOrigin(GeometricFacetQuantity):
     """UFL geometry representation: The reference cell coordinate corresponding to origin of a reference facet."""
@@ -270,13 +287,15 @@ class CellFacetOrigin(GeometricFacetQuantity):
 class Jacobian(GeometricCellQuantity):
     """UFL geometry representation: The Jacobian of the mapping from reference cell to spatial coordinates.
 
-    J_ij = dx_i/dX_j
+    .. math:: J_{ij} = \\frac{dx_i}{dX_j}
     """
     __slots__ = ()
     name = "J"
 
     @property
     def ufl_shape(self):
+        """Return the number of coordinates defined (i.e. the geometric dimension
+        of the domain)."""
         g = self._domain.geometric_dimension()
         t = self._domain.topological_dimension()
         return (g, t)
@@ -286,6 +305,7 @@ class Jacobian(GeometricCellQuantity):
         # Only true for a piecewise linear coordinate field in simplex cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
+
 @ufl_type()
 class FacetJacobian(GeometricFacetQuantity):
     """UFL geometry representation: The Jacobian of the mapping from reference facet to spatial coordinates.
@@ -303,7 +323,8 @@ class FacetJacobian(GeometricFacetQuantity):
     def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 1, "FacetJacobian is only defined for topological dimensions > 1.")
+        if t < 2:
+            error("FacetJacobian is only defined for topological dimensions >= 2.")
 
     @property
     def ufl_shape(self):
@@ -313,11 +334,13 @@ class FacetJacobian(GeometricFacetQuantity):
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # Only true for a piecewise linear coordinate field in simplex cells
+        # Only true for a piecewise linear coordinate field in simplex
+        # cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
+
 @ufl_type()
-class CellFacetJacobian(GeometricFacetQuantity): # dX/dXf
+class CellFacetJacobian(GeometricFacetQuantity):  # dX/dXf
     """UFL geometry representation: The Jacobian of the mapping from reference facet to reference cell coordinates.
 
     CFJ_ij = dX_i/dXf_j
@@ -328,7 +351,8 @@ class CellFacetJacobian(GeometricFacetQuantity): # dX/dXf
     def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 1, "CellFacetJacobian is only defined for topological dimensions > 1.")
+        if t < 2:
+            error("CellFacetJacobian is only defined for topological dimensions >= 2.")
 
     @property
     def ufl_shape(self):
@@ -337,9 +361,11 @@ class CellFacetJacobian(GeometricFacetQuantity): # dX/dXf
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # This is always a constant mapping between two reference coordinate systems.
+        # This is always a constant mapping between two reference
+        # coordinate systems.
         return True
 
+
 @ufl_type()
 class CellEdgeVectors(GeometricCellQuantity):
     """UFL geometry representation: The vectors between reference cell vertices for each edge in cell."""
@@ -349,7 +375,8 @@ class CellEdgeVectors(GeometricCellQuantity):
     def __init__(self, domain):
         GeometricCellQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 1, "CellEdgeVectors is only defined for topological dimensions >= 2.")
+        if t < 2:
+            error("CellEdgeVectors is only defined for topological dimensions >= 2.")
 
     @property
     def ufl_shape(self):
@@ -363,6 +390,7 @@ class CellEdgeVectors(GeometricCellQuantity):
         # This is always constant for a given cell type
         return True
 
+
 @ufl_type()
 class FacetEdgeVectors(GeometricFacetQuantity):
     """UFL geometry representation: The vectors between reference cell vertices for each edge in current facet."""
@@ -372,7 +400,8 @@ class FacetEdgeVectors(GeometricFacetQuantity):
     def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 2, "FacetEdgeVectors is only defined for topological dimensions >= 3.")
+        if t < 3:
+            error("FacetEdgeVectors is only defined for topological dimensions >= 3.")
 
     @property
     def ufl_shape(self):
@@ -400,9 +429,11 @@ class JacobianDeterminant(GeometricCellQuantity):
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # Only true for a piecewise linear coordinate field in simplex cells
+        # Only true for a piecewise linear coordinate field in simplex
+        # cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
+
 @ufl_type()
 class FacetJacobianDeterminant(GeometricFacetQuantity):
     """UFL geometry representation: The pseudo-determinant of the FacetJacobian."""
@@ -414,6 +445,7 @@ class FacetJacobianDeterminant(GeometricFacetQuantity):
         # Only true for a piecewise linear coordinate field in simplex cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
+
 @ufl_type()
 class CellFacetJacobianDeterminant(GeometricFacetQuantity):
     """UFL geometry representation: The pseudo-determinant of the CellFacetJacobian."""
@@ -422,7 +454,8 @@ class CellFacetJacobianDeterminant(GeometricFacetQuantity):
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # Only true for a piecewise linear coordinate field in simplex cells
+        # Only true for a piecewise linear coordinate field in simplex
+        # cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
 
@@ -439,15 +472,19 @@ class JacobianInverse(GeometricCellQuantity):
 
     @property
     def ufl_shape(self):
+        """Return the number of coordinates defined (i.e. the geometric dimension
+        of the domain)."""
         g = self._domain.geometric_dimension()
         t = self._domain.topological_dimension()
         return (t, g)
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # Only true for a piecewise linear coordinate field in simplex cells
+        # Only true for a piecewise linear coordinate field in simplex
+        # cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
+
 @ufl_type()
 class FacetJacobianInverse(GeometricFacetQuantity):
     """UFL geometry representation: The pseudo-inverse of the FacetJacobian."""
@@ -457,7 +494,8 @@ class FacetJacobianInverse(GeometricFacetQuantity):
     def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 1, "FacetJacobianInverse is only defined for topological dimensions > 1.")
+        if t < 2:
+            error("FacetJacobianInverse is only defined for topological dimensions >= 2.")
 
     @property
     def ufl_shape(self):
@@ -467,9 +505,11 @@ class FacetJacobianInverse(GeometricFacetQuantity):
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # Only true for a piecewise linear coordinate field in simplex cells
+        # Only true for a piecewise linear coordinate field in simplex
+        # cells
         return self._domain.is_piecewise_linear_simplex_domain()
 
+
 @ufl_type()
 class CellFacetJacobianInverse(GeometricFacetQuantity):
     """UFL geometry representation: The pseudo-inverse of the CellFacetJacobian."""
@@ -479,7 +519,8 @@ class CellFacetJacobianInverse(GeometricFacetQuantity):
     def __init__(self, domain):
         GeometricFacetQuantity.__init__(self, domain)
         t = self._domain.topological_dimension()
-        ufl_assert(t > 1, "CellFacetJacobianInverse is only defined for topological dimensions > 1.")
+        if t < 2:
+            error("CellFacetJacobianInverse is only defined for topological dimensions >= 2.")
 
     @property
     def ufl_shape(self):
@@ -502,16 +543,21 @@ class FacetNormal(GeometricFacetQuantity):
 
     @property
     def ufl_shape(self):
+        """Return the number of coordinates defined (i.e. the geometric dimension
+        of the domain)."""
         g = self._domain.geometric_dimension()
         return (g,)
 
     def is_cellwise_constant(self):
         "Return whether this expression is spatially constant over each cell."
-        # For product cells, this is only true for some but not all facets. Seems like too much work to fix right now.
-        # Only true for a piecewise linear coordinate field with simplex _facets_.
+        # For product cells, this is only true for some but not all
+        # facets. Seems like too much work to fix right now.  Only
+        # true for a piecewise linear coordinate field with simplex
+        # _facets_.
         is_piecewise_linear = self._domain.ufl_coordinate_element().degree() == 1
         return is_piecewise_linear and self._domain.ufl_cell().has_simplex_facets()
 
+
 @ufl_type()
 class CellNormal(GeometricCellQuantity):
     """UFL geometry representation: The upwards pointing normal vector of the current manifold cell."""
@@ -520,11 +566,14 @@ class CellNormal(GeometricCellQuantity):
 
     @property
     def ufl_shape(self):
+        """Return the number of coordinates defined (i.e. the geometric dimension
+        of the domain)."""
         g = self._domain.geometric_dimension()
-        #t = self._domain.topological_dimension()
-        #return (g-t,g) # TODO: Should it be CellNormals? For interval in 3D we have two!
+        # t = self._domain.topological_dimension()
+        # return (g-t,g) # TODO: Should it be CellNormals? For interval in 3D we have two!
         return (g,)
 
+
 @ufl_type()
 class ReferenceNormal(GeometricFacetQuantity):
     """UFL geometry representation: The outwards pointing normal vector of the current facet on the reference cell"""
@@ -537,16 +586,17 @@ class ReferenceNormal(GeometricFacetQuantity):
         return (t,)
 
 # TODO: Implement in apply_geometry_lowering and enable
-#@ufl_type()
-#class FacetTangents(GeometricFacetQuantity):
-#    """UFL geometry representation: The tangent vectors of the current facet."""
-#    __slots__ = ()
-#    name = "t"
+# @ufl_type()
+# class FacetTangents(GeometricFacetQuantity):
+#     """UFL geometry representation: The tangent vectors of the current facet."""
+#     __slots__ = ()
+#     name = "t"
 #
-#    def __init__(self, domain):
-#        GeometricFacetQuantity.__init__(self, domain)
-#        t = self._domain.topological_dimension()
-#        ufl_assert(t > 1, "FacetTangents is only defined for topological dimensions > 1.")
+#     def __init__(self, domain):
+#         GeometricFacetQuantity.__init__(self, domain)
+#         t = self._domain.topological_dimension()
+#         if t < 2:
+#             error("FacetTangents is only defined for topological dimensions >= 2.")
 #
 #    @property
 #    def ufl_shape(self):
@@ -562,8 +612,8 @@ class ReferenceNormal(GeometricFacetQuantity):
 #        return is_piecewise_linear and self._domain.ufl_cell().has_simplex_facets()
 
 # TODO: Implement in apply_geometry_lowering and enable
-#@ufl_type()
-#class CellTangents(GeometricCellQuantity):
+# @ufl_type()
+# class CellTangents(GeometricCellQuantity):
 #    """UFL geometry representation: The tangent vectors of the current manifold cell."""
 #    __slots__ = ()
 #    name = "cell_tangents"
@@ -578,8 +628,8 @@ class ReferenceNormal(GeometricFacetQuantity):
 # --- Types representing midpoint coordinates
 
 # TODO: Implement in the rest of fenics
-#@ufl_type()
-#class CellMidpoint(GeometricCellQuantity):
+# @ufl_type()
+# class CellMidpoint(GeometricCellQuantity):
 #    """UFL geometry representation: The midpoint coordinate of the current cell."""
 #    __slots__ = ()
 #    name = "cell_midpoint"
@@ -590,8 +640,8 @@ class ReferenceNormal(GeometricFacetQuantity):
 #        return (g,)
 
 # TODO: Implement in the rest of fenics
-#@ufl_type()
-#class FacetMidpoint(GeometricFacetQuantity):
+# @ufl_type()
+# class FacetMidpoint(GeometricFacetQuantity):
 #    """UFL geometry representation: The midpoint coordinate of the current facet."""
 #    __slots__ = ()
 #    name = "facet_midpoint"
@@ -606,60 +656,69 @@ class ReferenceNormal(GeometricFacetQuantity):
 
 # TODO: Clean up this set of types? Document!
 
+
 @ufl_type()
 class ReferenceCellVolume(GeometricCellQuantity):
     """UFL geometry representation: The volume of the reference cell."""
     __slots__ = ()
     name = "reference_cell_volume"
 
+
 @ufl_type()
 class ReferenceFacetVolume(GeometricFacetQuantity):
     """UFL geometry representation: The volume of the reference cell of the current facet."""
     __slots__ = ()
     name = "reference_facet_volume"
 
+
 @ufl_type()
 class CellVolume(GeometricCellQuantity):
     """UFL geometry representation: The volume of the cell."""
     __slots__ = ()
     name = "volume"
 
+
 @ufl_type()
 class Circumradius(GeometricCellQuantity):
     """UFL geometry representation: The circumradius of the cell."""
     __slots__ = ()
     name = "circumradius"
 
-#@ufl_type()
-#class CellSurfaceArea(GeometricCellQuantity):
+# @ufl_type()
+# class CellSurfaceArea(GeometricCellQuantity):
 #    """UFL geometry representation: The total surface area of the cell."""
 #    __slots__ = ()
 #    name = "surfacearea"
 
+
 @ufl_type()
-class FacetArea(GeometricFacetQuantity): # FIXME: Should this be allowed for interval domain?
+class FacetArea(GeometricFacetQuantity):  # FIXME: Should this be allowed for interval domain?
     """UFL geometry representation: The area of the facet."""
     __slots__ = ()
     name = "facetarea"
 
+
 @ufl_type()
 class MinCellEdgeLength(GeometricCellQuantity):
     """UFL geometry representation: The minimum edge length of the cell."""
     __slots__ = ()
     name = "mincelledgelength"
 
+
 @ufl_type()
 class MaxCellEdgeLength(GeometricCellQuantity):
     """UFL geometry representation: The maximum edge length of the cell."""
     __slots__ = ()
     name = "maxcelledgelength"
 
+
 @ufl_type()
 class MinFacetEdgeLength(GeometricFacetQuantity):
     """UFL geometry representation: The minimum edge length of the facet."""
     __slots__ = ()
     name = "minfacetedgelength"
 
+
 @ufl_type()
 class MaxFacetEdgeLength(GeometricFacetQuantity):
     """UFL geometry representation: The maximum edge length of the facet."""
@@ -683,13 +742,16 @@ class CellOrientation(GeometricCellQuantity):
     __slots__ = ()
     name = "cell_orientation"
 
+
 @ufl_type()
 class FacetOrientation(GeometricFacetQuantity):
     """UFL geometry representation: The orientation (+1/-1) of the current facet relative to the reference cell."""
     __slots__ = ()
     name = "facet_orientation"
 
-# This doesn't quite fit anywhere. Make a special set of symbolic terminal types instead?
+
+# This doesn't quite fit anywhere. Make a special set of symbolic
+# terminal types instead?
 @ufl_type()
 class QuadratureWeight(GeometricQuantity):
     """UFL geometry representation: The current quadrature weight.
diff --git a/ufl/index_combination_utils.py b/ufl/index_combination_utils.py
index f878b36..4d079ab 100644
--- a/ufl/index_combination_utils.py
+++ b/ufl/index_combination_utils.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Utilities for analysing and manipulating free index tuples"
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,13 +21,12 @@
 from six.moves import zip
 from six.moves import xrange as range
 
-from ufl.assertions import ufl_assert
 from ufl.log import error
 from ufl.core.multiindex import FixedIndex, Index, indices
 
 
-# FIXME: Some of these might be merged into one function, some might be optimized
-
+# FIXME: Some of these might be merged into one function, some might
+# be optimized
 
 def unique_sorted_indices(indices):
     """Given a list of (id, dim) tuples already sorted by id,
@@ -41,7 +40,8 @@ def unique_sorted_indices(indices):
             newindices.append(i)
             prev = i
         else:
-            ufl_assert(i[1] == prev[1], "Nonmatching dimensions for free indices with same id!")
+            if i[1] != prev[1]:
+                error("Nonmatching dimensions for free indices with same id!")
     return tuple(newindices)
 
 
@@ -102,7 +102,7 @@ def remove_indices(fi, fid, rfi):
     if not rfi:
         return fi, fid
 
-    rfip = sorted((r,p) for p, r in enumerate(rfi))
+    rfip = sorted((r, p) for p, r in enumerate(rfi))
 
     nrfi = len(rfi)
     nfi = len(fi)
@@ -158,15 +158,16 @@ def create_slice_indices(component, shape, fi):
                 repeated_indices.append(ind)
             free_indices.append(ind)
         elif isinstance(ind, FixedIndex):
-            ufl_assert(int(ind) < shape[len(all_indices)],
-                       "Index out of bounds.")
+            if int(ind) >= shape[len(all_indices)]:
+                error("Index out of bounds.")
             all_indices.append(ind)
         elif isinstance(ind, int):
-            ufl_assert(int(ind) < shape[len(all_indices)],
-                       "Index out of bounds.")
+            if int(ind) >= shape[len(all_indices)]:
+                error("Index out of bounds.")
             all_indices.append(FixedIndex(ind))
         elif isinstance(ind, slice):
-            ufl_assert(ind == slice(None), "Only full slices (:) allowed.")
+            if ind != slice(None):
+                error("Only full slices (:) allowed.")
             i = Index()
             slice_indices.append(i)
             all_indices.append(i)
@@ -178,8 +179,8 @@ def create_slice_indices(component, shape, fi):
         else:
             error("Not expecting {0}.".format(ind))
 
-    ufl_assert(len(all_indices) == len(shape),
-               "Component and shape length don't match.")
+    if len(all_indices) != len(shape):
+        error("Component and shape length don't match.")
 
     return tuple(all_indices), tuple(slice_indices), tuple(repeated_indices)
 
@@ -204,7 +205,8 @@ def merge_nonoverlapping_indices(a, b):
     if s:
         free_indices, index_dimensions = zip(*s)
         # Consistency checks
-        ufl_assert(len(set(free_indices)) == len(free_indices), "Not expecting repeated indices.")
+        if len(set(free_indices)) != len(free_indices):
+            error("Not expecting repeated indices.")
     else:
         free_indices, index_dimensions = (), ()
     return free_indices, index_dimensions
@@ -244,7 +246,9 @@ def merge_overlapping_indices(afi, afid, bfi, bfid):
             index_dimensions.append(d)
 
     # Consistency checks
-    ufl_assert(len(set(free_indices)) == len(free_indices), "Not expecting repeated indices left.")
-    ufl_assert(len(free_indices) + 2*len(repeated_indices) == an + bn, "Expecting only twice repeated indices.")
+    if len(set(free_indices)) != len(free_indices):
+        error("Not expecting repeated indices left.")
+    if len(free_indices) + 2*len(repeated_indices) != an + bn:
+        error("Expecting only twice repeated indices.")
 
     return tuple(free_indices), tuple(index_dimensions), tuple(repeated_indices), tuple(repeated_index_dimensions)
diff --git a/ufl/indexed.py b/ufl/indexed.py
index bc685b8..b77de1d 100644
--- a/ufl/indexed.py
+++ b/ufl/indexed.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module defines the Indexed class."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,39 +20,64 @@
 
 from six.moves import zip
 from ufl.log import error
-from ufl.core.expr import Expr
+from ufl.utils.py23 import as_native_strings
+from ufl.constantvalue import Zero
+from ufl.core.expr import Expr, ufl_err_str
+from ufl.core.ufl_type import ufl_type
 from ufl.core.operator import Operator
-from ufl.core.multiindex import Index, FixedIndex, MultiIndex, as_multi_index
+from ufl.core.multiindex import Index, FixedIndex, MultiIndex
 from ufl.index_combination_utils import unique_sorted_indices, merge_unique_indices
 from ufl.precedence import parstr
-from ufl.utils.dicts import EmptyDict
-from ufl.core.ufl_type import ufl_type
 
-#--- Indexed expression ---
+
+# --- Indexed expression ---
 
 @ufl_type(is_shaping=True, num_ops=2, is_terminal_modifier=True)
 class Indexed(Operator):
-    __slots__ = ("ufl_free_indices", "ufl_index_dimensions",)
+    __slots__ = as_native_strings((
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+    ))
+
+    def __new__(cls, expression, multiindex):
+        if isinstance(expression, Zero):
+            # Zero-simplify indexed Zero objects
+            shape = expression.ufl_shape
+            efi = expression.ufl_free_indices
+            efid = expression.ufl_index_dimensions
+            fi = list(zip(efi, efid))
+            for pos, ind in enumerate(multiindex._indices):
+                if isinstance(ind, Index):
+                    fi.append((ind.count(), shape[pos]))
+            fi = unique_sorted_indices(sorted(fi))
+            if fi:
+                fi, fid = zip(*fi)
+            else:
+                fi, fid = (), ()
+            return Zero(shape=(), free_indices=fi, index_dimensions=fid)
+        else:
+            return Operator.__new__(cls)
 
     def __init__(self, expression, multiindex):
         # Store operands
         Operator.__init__(self, (expression, multiindex))
 
-
         # Error checking
         if not isinstance(expression, Expr):
-            error("Expecting Expr instance, not %s." % repr(expression))
+            error("Expecting Expr instance, not %s." % ufl_err_str(expression))
         if not isinstance(multiindex, MultiIndex):
-            error("Expecting MultiIndex instance, not %s." % repr(multiindex))
+            error("Expecting MultiIndex instance, not %s." % ufl_err_str(multiindex))
 
         shape = expression.ufl_shape
 
         # Error checking
         if len(shape) != len(multiindex):
             error("Invalid number of indices (%d) for tensor "
-                "expression of rank %d:\n\t%r\n"
-                % (len(multiindex), len(expression.ufl_shape), expression))
-        if any(int(di) >= int(si) for si, di in zip(shape, multiindex) if isinstance(di, FixedIndex)):
+                  "expression of rank %d:\n\t%s\n"
+                  % (len(multiindex), len(expression.ufl_shape), ufl_err_str(expression)))
+        if any(int(di) >= int(si)
+               for si, di in zip(shape, multiindex)
+               if isinstance(di, FixedIndex)):
             error("Fixed index out of range!")
 
         # Build tuples of free index ids and dimensions
@@ -70,10 +95,13 @@ class Indexed(Operator):
                 fi, fid = (), ()
 
         else:
-            mfiid = [(ind.count(), shape[pos]) for pos, ind in enumerate(multiindex._indices) if isinstance(ind, Index)]
+            mfiid = [(ind.count(), shape[pos])
+                     for pos, ind in enumerate(multiindex._indices)
+                     if isinstance(ind, Index)]
             mfi, mfid = zip(*mfiid) if mfiid else ((), ())
-            fi, fid = merge_unique_indices(expression.ufl_free_indices, expression.ufl_index_dimensions, mfi, mfid)
-
+            fi, fid = merge_unique_indices(expression.ufl_free_indices,
+                                           expression.ufl_index_dimensions,
+                                           mfi, mfid)
 
         # Cache free index and dimensions
         self.ufl_free_indices = fi
@@ -90,10 +118,8 @@ class Indexed(Operator):
             return A.evaluate(x, mapping, component, index_values)
 
     def __str__(self):
-        return "%s[%s]" % (parstr(self.ufl_operands[0], self), self.ufl_operands[1])
-
-    def __repr__(self):
-        return "Indexed(%r, %r)" % self.ufl_operands
+        return "%s[%s]" % (parstr(self.ufl_operands[0], self),
+                           self.ufl_operands[1])
 
     def __getitem__(self, key):
-        error("Attempting to index with %r, but object is already indexed: %r" % (key, self))
+        error("Attempting to index with %s, but object is already indexed: %s" % (ufl_err_str(key), ufl_err_str(self)))
diff --git a/ufl/indexing.py b/ufl/indexing.py
deleted file mode 100644
index 53c6e9b..0000000
--- a/ufl/indexing.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-"""This module defines the single index types and some internal index utilities."""
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
-# TODO: Fix imports and remove this file
-from ufl.core.multiindex import IndexBase, Index, FixedIndex, MultiIndex, indices, as_multi_index
diff --git a/ufl/indexsum.py b/ufl/indexsum.py
index 678c249..bc53c30 100644
--- a/ufl/indexsum.py
+++ b/ufl/indexsum.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module defines the IndexSum class."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,29 +21,33 @@
 from six.moves import xrange as range
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
-from ufl.core.expr import Expr
+from ufl.utils.py23 import as_native_strings
+from ufl.core.ufl_type import ufl_type
+from ufl.core.expr import Expr, ufl_err_str
 from ufl.core.operator import Operator
-from ufl.core.multiindex import Index, MultiIndex, as_multi_index
+from ufl.core.multiindex import MultiIndex
 from ufl.precedence import parstr
-from ufl.utils.dicts import EmptyDict
-from ufl.core.ufl_type import ufl_type
 from ufl.constantvalue import Zero
 
-#--- Sum over an index ---
+
+# --- Sum over an index ---
 
 @ufl_type(num_ops=2)
 class IndexSum(Operator):
-    __slots__ = ("_dimension", "ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings((
+        "_dimension",
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+    ))
 
     def __new__(cls, summand, index):
         # Error checks
         if not isinstance(summand, Expr):
-            error("Expecting Expr instance, not %s." % repr(summand))
+            error("Expecting Expr instance, got %s" % ufl_err_str(summand))
         if not isinstance(index, MultiIndex):
-            error("Expecting MultiIndex instance, not %s." % repr(index))
+            error("Expecting MultiIndex instance, got %s" % ufl_err_str(index))
         if len(index) != 1:
-            error("Expecting a single Index only.")
+            error("Expecting a single Index onlym got %d." % len(index))
 
         # Simplification to zero
         if isinstance(summand, Zero):
@@ -83,12 +87,11 @@ class IndexSum(Operator):
         tmp = 0
         for k in range(self._dimension):
             index_values.push(i, k)
-            tmp += self.ufl_operands[0].evaluate(x, mapping, component, index_values)
+            tmp += self.ufl_operands[0].evaluate(x, mapping, component,
+                                                 index_values)
             index_values.pop()
         return tmp
 
     def __str__(self):
-        return "sum_{%s} %s " % (str(self.ufl_operands[1]), parstr(self.ufl_operands[0], self))
-
-    def __repr__(self):
-        return "IndexSum(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
+        return "sum_{%s} %s " % (str(self.ufl_operands[1]),
+                                 parstr(self.ufl_operands[0], self))
diff --git a/ufl/integral.py b/ufl/integral.py
index e8b0e30..c127ff9 100644
--- a/ufl/integral.py
+++ b/ufl/integral.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """The Integral class."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,31 +19,38 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Anders Logg, 2008-2009
+# Modified by Massimiliano Leoni, 2016.
 
+# import six
 import ufl
-from ufl.log import error, warning, deprecate
-from ufl.assertions import ufl_assert
+from ufl.log import error
 from ufl.core.expr import Expr
-from ufl.checks import (is_true_ufl_scalar, is_python_scalar, is_globally_constant,
-                        is_scalar_constant_expression)
-from ufl.measure import Measure
+from ufl.checks import is_python_scalar, is_scalar_constant_expression
+from ufl.measure import Measure  # noqa
 from ufl.protocols import id_or_none
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 
 # Export list for ufl.classes
-__all_classes__ = ["Integral"]
+__all_classes__ = as_native_strings(["Integral"])
 
+
+# @six.python_2_unicode_compatible
 class Integral(object):
     "An integral over a single domain."
-    __slots__ = ("_integrand",
-                 "_integral_type",
-                 "_ufl_domain",
-                 "_subdomain_id",
-                 "_metadata",
-                 "_subdomain_data",
-                 )
-    def __init__(self, integrand, integral_type, domain, subdomain_id, metadata, subdomain_data):
-        ufl_assert(isinstance(integrand, Expr),
-                   "Expecting integrand to be an Expr instance.")
+    __slots__ = as_native_strings((
+        "_integrand",
+        "_integral_type",
+        "_ufl_domain",
+        "_subdomain_id",
+        "_metadata",
+        "_subdomain_data",
+    ))
+
+    def __init__(self, integrand, integral_type, domain, subdomain_id,
+                 metadata, subdomain_data):
+        if not isinstance(integrand, Expr):
+            error("Expecting integrand to be an Expr instance.")
         self._integrand = integrand
         self._integral_type = integral_type
         self._ufl_domain = domain
@@ -76,16 +83,17 @@ class Integral(object):
         return Integral(integrand, integral_type, domain, subdomain_id, metadata, subdomain_data)
 
     def integrand(self):
-        "Return the integrand expression, which is an Expr instance."
+        "Return the integrand expression, which is an ``Expr`` instance."
         return self._integrand
 
     def integral_type(self):
         "Return the domain type of this integral."
         return self._integral_type
 
-    def domain(self):
-        deprecate("Integral.domain() is deprecated, please use .ufl_domain() instead.")
-        return self.ufl_domain()
+    #def domain(self):
+    #    "Deprecated, please use .ufl_domain() instead."
+    #    deprecate("Integral.domain() is deprecated, please use .ufl_domain() instead.")
+    #    return self.ufl_domain()
 
     def ufl_domain(self):
         "Return the integration domain of this integral."
@@ -107,16 +115,20 @@ class Integral(object):
         return self.reconstruct(-self._integrand)
 
     def __mul__(self, scalar):
-        ufl_assert(is_python_scalar(scalar),
-                   "Cannot multiply an integral with non-constant values.")
+        if not is_python_scalar(scalar):
+            error("Cannot multiply an integral with non-constant values.")
         return self.reconstruct(scalar*self._integrand)
 
     def __rmul__(self, scalar):
-        ufl_assert(is_scalar_constant_expression(scalar),
-                   "An integral can only be multiplied by a "
-                   "globally constant scalar expression.")
+        if not is_scalar_constant_expression(scalar):
+            error("An integral can only be multiplied by a "
+                  "globally constant scalar expression.")
         return self.reconstruct(scalar*self._integrand)
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         fmt = "{ %s } * %s(%s[%s], %s)"
         mname = ufl.measure.integral_type_to_measure_name[self._integral_type]
@@ -124,17 +136,24 @@ class Integral(object):
         return s
 
     def __repr__(self):
-        return "Integral(%r, %r, %r, %r, %r, %r)" % (
-            self._integrand, self._integral_type, self._ufl_domain, self._subdomain_id, self._metadata, self._subdomain_data)
+        r = "Integral(%s, %s, %s, %s, %s, %s)" % (
+            repr(self._integrand),
+            repr(self._integral_type),
+            repr(self._ufl_domain),
+            repr(self._subdomain_id),
+            repr(self._metadata),
+            repr(self._subdomain_data),
+            )
+        return as_native_str(r)
 
     def __eq__(self, other):
-        return (isinstance(other, Integral)
-            and self._integral_type == other._integral_type
-            and self._ufl_domain == other._ufl_domain
-            and self._subdomain_id == other._subdomain_id
-            and self._integrand == other._integrand
-            and self._metadata == other._metadata
-            and id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data))
+        return (isinstance(other, Integral) and
+                self._integral_type == other._integral_type and
+                self._ufl_domain == other._ufl_domain and
+                self._subdomain_id == other._subdomain_id and
+                self._integrand == other._integrand and
+                self._metadata == other._metadata and
+                id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data))
 
     def __hash__(self):
         # Assuming few collisions by ignoring hash(self._metadata)
diff --git a/ufl/log.py b/ufl/log.py
index 0d29a5e..9430b72 100644
--- a/ufl/log.py
+++ b/ufl/log.py
@@ -2,7 +2,7 @@
 """This module provides functions used by the UFL implementation to
 output messages. These may be redirected by the user of UFL."""
 
-# Copyright (C) 2005-2015 Anders Logg and Martin Sandve Alnaes
+# Copyright (C) 2005-2016 Anders Logg and Martin Sandve Alnaes
 #
 # This file is part of UFL.
 #
@@ -20,42 +20,52 @@ output messages. These may be redirected by the user of UFL."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Johan Hake, 2009.
+# Modified by Massimiliano Leoni, 2016
 
 import sys
 import types
 import logging
-
-log_functions = ["log", "debug", "info", "deprecate", "warning", "error", "begin", "end",
-                 "set_level", "push_level", "pop_level", "set_indent", "add_indent",
-                 "set_handler", "get_handler", "get_logger", "add_logfile", "set_prefix",
+from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL  # noqa: F401
+from ufl.utils.py23 import as_native_strings
+
+log_functions = ["log", "debug", "info", "deprecate", "warning", "error",
+                 "begin", "end",
+                 "set_level", "push_level", "pop_level", "set_indent",
+                 "add_indent",
+                 "set_handler", "get_handler", "get_logger", "add_logfile",
+                 "set_prefix",
                  "info_red", "info_green", "info_blue",
                  "warning_red", "warning_green", "warning_blue"]
 
-__all__ = log_functions + ["DEBUG", "INFO", "DEPRECATE", "WARNING", "ERROR",
-                           "CRITICAL", "Logger", "log_functions"]
+__all__ = as_native_strings(
+    log_functions +
+    ["Logger", "log_functions"] +
+    ["DEBUG", "INFO", "DEPRECATE", "WARNING", "ERROR", "CRITICAL"]
+)
 
-# Import default log levels
-from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL
 DEPRECATE = (INFO + WARNING) // 2
 
-# This is used to override emit() in StreamHandler for printing without newline
+
+# This is used to override emit() in StreamHandler for printing
+# without newline
 def emit(self, record):
     message = self.format(record)
     format_string = "%s" if getattr(record, "continued", False) else "%s\n"
     self.stream.write(format_string % message)
     self.flush()
 
-# Colors if the terminal supports it (disabled e.g. when piped to file)
-import sys
+# Colors if the terminal supports it (disabled e.g. when piped to
+# file)
 if sys.stdout.isatty() and sys.stderr.isatty():
-    RED   = "\033[1;37;31m%s\033[0m"
-    BLUE  = "\033[1;37;34m%s\033[0m"
+    RED = "\033[1;37;31m%s\033[0m"
+    BLUE = "\033[1;37;34m%s\033[0m"
     GREEN = "\033[1;37;32m%s\033[0m"
 else:
-    RED   = "%s"
-    BLUE  = "%s"
+    RED = "%s"
+    BLUE = "%s"
     GREEN = "%s"
 
+
 # Logger class
 class Logger:
 
@@ -89,10 +99,11 @@ class Logger:
         self._prefix = ""
 
     def add_logfile(self, filename=None, mode="a", level=DEBUG):
+        "Add a log file."
         if filename is None:
             filename = "%s.log" % self._name
         if filename in self._logfiles:
-            self.warning("Trying to add logfile %s multiple times." % filename)
+            self.warning("Adding logfile %s multiple times." % filename)
             return
         h = logging.FileHandler(filename, mode)
         h.emit = types.MethodType(emit, h)
@@ -102,13 +113,15 @@ class Logger:
         return h
 
     def get_logfile_handler(self, filename):
+        "Gets the handler to the file identified by the given file name."
         return self._logfiles[filename]
 
     def log(self, level, *message):
-        "Write a log message on given log level"
+        "Write a log message on given log level."
         text = self._format_raw(*message)
         if len(text) >= 3 and text[-3:] == "...":
-            self._log.log(level, self._format(*message), extra={"continued": True})
+            self._log.log(level, self._format(*message),
+                          extra={"continued": True})
         else:
             self._log.log(level, self._format(*message))
 
@@ -182,7 +195,6 @@ class Logger:
     def set_level(self, level):
         "Set log level."
         self._level_stack[-1] = level
-        #self._log.setLevel(level)
         self._handler.setLevel(level)
 
     def set_indent(self, level):
@@ -199,15 +211,15 @@ class Logger:
 
     def set_handler(self, handler):
         """Replace handler for logging.
-        To add additional handlers instead
-        of replacing the existing, use
-        log.get_logger().addHandler(myhandler).
+        To add additional handlers instead of replacing the existing one, use
+        `log.get_logger().addHandler(myhandler)`.
         See the logging module for more details.
         """
         self._log.removeHandler(self._handler)
         self._log.addHandler(handler)
         self._handler = handler
-        handler.emit = types.MethodType(emit, self._handler, self._handler.__class__)
+        handler.emit = types.MethodType(emit, self._handler,
+                                        self._handler.__class__)
 
     def get_logger(self):
         "Return message logger."
@@ -226,16 +238,22 @@ class Logger:
         "Format message without indentation."
         return message[0] % message[1:]
 
-#--- Set up global log functions ---
 
-# Base class for UFL exceptions
+# --- Set up global log functions ---
+
 class UFLException(Exception):
-    "Base class for UFL exceptions"
+    "Base class for UFL exceptions."
     pass
 
+
+class UFLValueError(UFLException):
+    "Value type error."
+    pass
+
+
 ufl_logger = Logger("UFL", UFLException)
 
 for foo in log_functions:
     exec("%s = ufl_logger.%s" % (foo, foo))
 
-set_level(DEPRECATE)
+set_level(DEPRECATE)  # noqa
diff --git a/ufl/mathfunctions.py b/ufl/mathfunctions.py
index be1fdda..8dd2e80 100644
--- a/ufl/mathfunctions.py
+++ b/ufl/mathfunctions.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """This module provides basic mathematical functions."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -22,12 +22,11 @@
 # Modified by Kristian B. Oelgaard, 2011
 
 import math
+from ufl.utils.py23 import as_native_strings
 from ufl.log import warning, error
-from ufl.assertions import ufl_assert
 from ufl.core.operator import Operator
-from ufl.constantvalue import is_true_ufl_scalar, ScalarValue, Zero, FloatValue, IntValue, as_ufl
-from ufl.utils.dicts import EmptyDict
 from ufl.core.ufl_type import ufl_type
+from ufl.constantvalue import is_true_ufl_scalar, ScalarValue, Zero, FloatValue, IntValue, as_ufl
 
 """
 TODO: Include additional functions available in <cmath> (need derivatives as well):
@@ -50,17 +49,20 @@ Implementation in C++ std::tr1:: or boost::math::tr1::
 - BesselY: cyl_neumann(nu, x)
 """
 
-#--- Function representations ---
+
+# --- Function representations ---
 
 @ufl_type(is_abstract=True, is_scalar=True, num_ops=1)
 class MathFunction(Operator):
     "Base class for all unary scalar math functions."
     # Freeze member variables for objects in this class
-    __slots__ = ("_name",)
+    __slots__ = as_native_strings(("_name",))
+
     def __init__(self, name, argument):
         Operator.__init__(self, (argument,))
-        ufl_assert(is_true_ufl_scalar(argument), "Expecting scalar argument.")
-        self._name     = name
+        if not is_true_ufl_scalar(argument):
+            error("Expecting scalar argument.")
+        self._name = name
 
     def evaluate(self, x, mapping, component, index_values):
         a = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
@@ -74,12 +76,11 @@ class MathFunction(Operator):
     def __str__(self):
         return "%s(%s)" % (self._name, self.ufl_operands[0])
 
-    def __repr__(self):
-        return "%s(%r)" % (self._name, self.ufl_operands[0])
 
 @ufl_type()
 class Sqrt(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.sqrt(float(argument)))
@@ -88,9 +89,11 @@ class Sqrt(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "sqrt", argument)
 
+
 @ufl_type()
 class Exp(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.exp(float(argument)))
@@ -99,9 +102,11 @@ class Exp(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "exp", argument)
 
+
 @ufl_type()
 class Ln(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.log(float(argument)))
@@ -114,9 +119,11 @@ class Ln(MathFunction):
         a = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
         return math.log(a)
 
+
 @ufl_type()
 class Cos(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.cos(float(argument)))
@@ -125,9 +132,11 @@ class Cos(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "cos", argument)
 
+
 @ufl_type()
 class Sin(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.sin(float(argument)))
@@ -136,9 +145,11 @@ class Sin(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "sin", argument)
 
+
 @ufl_type()
 class Tan(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.tan(float(argument)))
@@ -147,9 +158,11 @@ class Tan(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "tan", argument)
 
+
 @ufl_type()
 class Cosh(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.cosh(float(argument)))
@@ -158,9 +171,11 @@ class Cosh(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "cosh", argument)
 
+
 @ufl_type()
 class Sinh(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.sinh(float(argument)))
@@ -169,9 +184,11 @@ class Sinh(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "sinh", argument)
 
+
 @ufl_type()
 class Tanh(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.tanh(float(argument)))
@@ -180,9 +197,11 @@ class Tanh(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "tanh", argument)
 
+
 @ufl_type()
 class Acos(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.acos(float(argument)))
@@ -191,9 +210,11 @@ class Acos(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "acos", argument)
 
+
 @ufl_type()
 class Asin(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.asin(float(argument)))
@@ -202,9 +223,11 @@ class Asin(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "asin", argument)
 
+
 @ufl_type()
 class Atan(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             return FloatValue(math.atan(float(argument)))
@@ -213,6 +236,7 @@ class Atan(MathFunction):
     def __init__(self, argument):
         MathFunction.__init__(self, "atan", argument)
 
+
 @ufl_type(is_scalar=True, num_ops=2)
 class Atan2(Operator):
     __slots__ = ()
@@ -224,8 +248,10 @@ class Atan2(Operator):
 
     def __init__(self, arg1, arg2):
         Operator.__init__(self, (arg1, arg2))
-        ufl_assert(is_true_ufl_scalar(arg1), "Expecting scalar argument 1.")
-        ufl_assert(is_true_ufl_scalar(arg2), "Expecting scalar argument 2.")
+        if not is_true_ufl_scalar(arg1):
+            error("Expecting scalar argument 1.")
+        if not is_true_ufl_scalar(arg2):
+            error("Expecting scalar argument 2.")
 
     def evaluate(self, x, mapping, component, index_values):
         a = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
@@ -240,9 +266,6 @@ class Atan2(Operator):
     def __str__(self):
         return "atan_2(%s,%s)" % (self.ufl_operands[0], self.ufl_operands[1])
 
-    def __repr__(self):
-        return "atan_2(%s,%s)" % (self.ufl_operands[0], self.ufl_operands[1])
-
 
 def _find_erf():
     import math
@@ -253,9 +276,11 @@ def _find_erf():
         return scipy.special.erf
     return None
 
+
 @ufl_type()
 class Erf(MathFunction):
     __slots__ = ()
+
     def __new__(cls, argument):
         if isinstance(argument, (ScalarValue, Zero)):
             erf = _find_erf()
@@ -273,14 +298,17 @@ class Erf(MathFunction):
             error("No python implementation of erf available on this system, cannot evaluate. Upgrade python or install scipy.")
         return erf(a)
 
+
 @ufl_type(is_abstract=True, is_scalar=True, num_ops=2)
 class BesselFunction(Operator):
     "Base class for all bessel functions"
-    # Freeze member variables for objects in this class
-    __slots__ = ("_name", "_classname")
+    __slots__ = as_native_strings(("_name", "_classname"))
+
     def __init__(self, name, classname, nu, argument):
-        ufl_assert(is_true_ufl_scalar(nu), "Expecting scalar nu.")
-        ufl_assert(is_true_ufl_scalar(argument), "Expecting scalar argument.")
+        if not is_true_ufl_scalar(nu):
+            error("Expecting scalar nu.")
+        if not is_true_ufl_scalar(argument):
+            error("Expecting scalar argument.")
 
         # Use integer representation if suitable
         fnu = float(nu)
@@ -293,7 +321,7 @@ class BesselFunction(Operator):
         Operator.__init__(self, (nu, argument))
 
         self._classname = classname
-        self._name     = name
+        self._name = name
 
     def evaluate(self, x, mapping, component, index_values):
         a = self.ufl_operands[1].evaluate(x, mapping, component, index_values)
@@ -306,37 +334,44 @@ class BesselFunction(Operator):
             nu = int(self.ufl_operands[0])
             functype = 'n' if name != 'i' else 'v'
         else:
-            nu = self.ufl_operands[0].evaluate(x, mapping, component, index_values)
+            nu = self.ufl_operands[0].evaluate(x, mapping, component,
+                                               index_values)
             functype = 'v'
         func = getattr(scipy.special, name + functype)
         return func(nu, a)
 
     def __str__(self):
-        return "%s(%s, %s)" % (self._name, self.ufl_operands[0], self.ufl_operands[1])
+        return "%s(%s, %s)" % (self._name, self.ufl_operands[0],
+                               self.ufl_operands[1])
 
-    def __repr__(self):
-        return "%s(%r, %r)" % (self._classname, self.ufl_operands[0], self.ufl_operands[1])
 
 @ufl_type()
 class BesselJ(BesselFunction):
     __slots__ = ()
+
     def __init__(self, nu, argument):
         BesselFunction.__init__(self, "cyl_bessel_j", "BesselJ", nu, argument)
 
+
 @ufl_type()
 class BesselY(BesselFunction):
     __slots__ = ()
+
     def __init__(self, nu, argument):
         BesselFunction.__init__(self, "cyl_bessel_y", "BesselY", nu, argument)
 
+
 @ufl_type()
 class BesselI(BesselFunction):
     __slots__ = ()
+
     def __init__(self, nu, argument):
         BesselFunction.__init__(self, "cyl_bessel_i", "BesselI", nu, argument)
 
+
 @ufl_type()
 class BesselK(BesselFunction):
     __slots__ = ()
+
     def __init__(self, nu, argument):
         BesselFunction.__init__(self, "cyl_bessel_k", "BesselK", nu, argument)
diff --git a/ufl/measure.py b/ufl/measure.py
index 3c0f629..473d972 100644
--- a/ufl/measure.py
+++ b/ufl/measure.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """The Measure class."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,10 +18,16 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
-# Modified by Anders Logg 2008-2015
+# Modified by Anders Logg 2008-2016
+# Modified by Massimiliano Leoni, 2016.
 
-from ufl.assertions import ufl_assert
-from ufl.log import error, warning, deprecate
+#import six
+from six import string_types
+import numbers
+
+from ufl.utils.py23 import as_native_strings
+from ufl.utils.py23 import as_native_str
+from ufl.log import error, deprecate
 from ufl.core.expr import Expr
 from ufl.checks import is_true_ufl_scalar
 from ufl.constantvalue import as_ufl
@@ -31,7 +37,7 @@ from ufl.protocols import id_or_none, metadata_equal, metadata_hashdata
 
 
 # Export list for ufl.classes
-__all_classes__ = ["Measure", "MeasureSum", "MeasureProduct"]
+__all_classes__ = as_native_strings(["Measure", "MeasureSum", "MeasureProduct"])
 
 
 # TODO: Design a class IntegralType(name, shortname, codim, num_cells, ...)?
@@ -41,68 +47,80 @@ __all_classes__ = ["Measure", "MeasureSum", "MeasureProduct"]
 _integral_types = [
     # === Integration over full topological dimension:
     ("cell", "dx"),                     # Over cells of a mesh
-    #("macro_cell", "dE"),              # Over a group of adjacent cells (TODO: Arbitrary cell group? Not currently used.)
+    # ("macro_cell", "dE"),              # Over a group of adjacent cells (TODO: Arbitrary cell group? Not currently used.)
 
     # === Integration over topological dimension - 1:
     ("exterior_facet", "ds"),           # Over one-sided exterior facets of a mesh
     ("interior_facet", "dS"),           # Over two-sided facets between pairs of adjacent cells of a mesh
 
     # === Integration over topological dimension 0
-    ("vertex", "dP"),                   # Over vertices of a mesh
-    #("vertex", "dV"),                  # TODO: Use this over vertices?
-    #("point", "dP"),                   # TODO: Use this over arbitrary points inside cells?
+    ("vertex", "dP"),                    # Over vertices of a mesh
+    # ("vertex", "dV"),                  # TODO: Use this over vertices?
+    # ("point", "dP"),                   # TODO: Use this over arbitrary points inside cells?
 
     # === Integration over custom domains
-    ("custom",    "dc"),                # Over custom user-defined domains (run-time quadrature points)
-    ("cutcell",   "dC"),                # Over a cell with some part cut away (run-time quadrature points)
-    ("interface", "dI"),                # Over a facet fragment overlapping with two or more cells (run-time quadrature points)
-    ("overlap",   "dO"),                # Over a cell fragment overlapping with two or more cells (run-time quadrature points)
+    ("custom", "dc"),                 # Over custom user-defined domains (run-time quadrature points)
+    ("cutcell", "dC"),                # Over a cell with some part cut away (run-time quadrature points)
+    ("interface", "dI"),              # Over a facet fragment overlapping with two or more cells (run-time quadrature points)
+    ("overlap", "dO"),                # Over a cell fragment overlapping with two or more cells (run-time quadrature points)
 
     # === Firedrake specific hacks on the way out:
-    # TODO: Remove these, firedrake can use metadata instead and create the measure objects in firedrake:
+    # TODO: Remove these, firedrake can use metadata instead
+    # and create the measure objects in firedrake:
     ("exterior_facet_bottom", "ds_b"),  # Over bottom facets on extruded mesh
-    ("exterior_facet_top",    "ds_t"),  # Over top facets on extruded mesh
-    ("exterior_facet_vert",   "ds_v"),  # Over side facets of an extruded mesh
-    ("interior_facet_horiz",  "dS_h"),  # Over horizontal facets of an extruded mesh
-    ("interior_facet_vert",   "dS_v"),  # Over vertical facets of an extruded mesh
-    ]
+    ("exterior_facet_top", "ds_t"),     # Over top facets on extruded mesh
+    ("exterior_facet_vert", "ds_v"),    # Over side facets of an extruded mesh
+    ("interior_facet_horiz", "dS_h"),   # Over horizontal facets of an extruded mesh
+    ("interior_facet_vert", "dS_v"),  # Over vertical facets of an extruded mesh
+]
+
 integral_type_to_measure_name = dict((l, s) for l, s in _integral_types)
 measure_name_to_integral_type = dict((s, l) for l, s in _integral_types)
+
 custom_integral_types = ("custom", "cutcell", "interface", "overlap")
+point_integral_types = ("vertex",)  # "point")
+facet_integral_types = ("exterior_facet", "interior_facet")
+
 
 def register_integral_type(integral_type, measure_name):
     global integral_type_to_measure_name, measure_name_to_integral_type
-    ufl_assert(measure_name == integral_type_to_measure_name.get(integral_type, measure_name),
-               "Integral type already added with different measure name!")
-    ufl_assert(integral_type == measure_name_to_integral_type.get(measure_name, integral_type),
-               "Measure name already used for another domain type!")
+    if measure_name != integral_type_to_measure_name.get(integral_type, measure_name):
+        error("Integral type already added with different measure name!")
+    if integral_type != measure_name_to_integral_type.get(measure_name, integral_type):
+        error("Measure name already used for another domain type!")
     integral_type_to_measure_name[integral_type] = measure_name
     measure_name_to_integral_type[measure_name] = integral_type
 
+
 def as_integral_type(integral_type):
     "Map short name to long name and require a valid one."
     integral_type = integral_type.replace(" ", "_")
-    integral_type = measure_name_to_integral_type.get(integral_type, integral_type)
-    ufl_assert(integral_type in integral_type_to_measure_name,
-               "Invalid integral_type.")
+    integral_type = measure_name_to_integral_type.get(integral_type,
+                                                      integral_type)
+    if integral_type not in integral_type_to_measure_name:
+        error("Invalid integral_type.")
     return integral_type
 
+
 def integral_types():
     "Return a tuple of all domain type strings."
     return tuple(sorted(integral_type_to_measure_name.keys()))
 
+
 def measure_names():
     "Return a tuple of all measure name strings."
     return tuple(sorted(measure_name_to_integral_type.keys()))
 
+
+# @six.python_2_unicode_compatible
 class Measure(object):
-    __slots__ = (
+    __slots__ = as_native_strings((
         "_integral_type",
         "_domain",
         "_subdomain_id",
         "_metadata",
         "_subdomain_data",
-        )
+        ))
     """Representation of an integration measure.
 
     The Measure object holds information about integration properties to be
@@ -110,12 +128,11 @@ class Measure(object):
     """
 
     def __init__(self,
-                 integral_type, # "dx" etc
+                 integral_type,  # "dx" etc
                  domain=None,
                  subdomain_id="everywhere",
                  metadata=None,
-                 subdomain_data=None
-                 ):
+                 subdomain_data=None):
         """
         integral_type:
             str, one of "cell", etc.,
@@ -142,25 +159,32 @@ class Measure(object):
 
         # Check that we either have a proper AbstractDomain or none
         self._domain = None if domain is None else as_domain(domain)
-        ufl_assert(self._domain is None or isinstance(self._domain, AbstractDomain), "Invalid domain.")
+        if not (self._domain is None
+                or isinstance(self._domain, AbstractDomain)):
+            error("Invalid domain.")
 
         # Store subdomain data
         self._subdomain_data = subdomain_data
-        # FIXME: Cannot require this (yet) because we currently have no way to implement ufl_id for dolfin SubDomain
-        #ufl_assert(self._subdomain_data is None or hasattr(self._subdomain_data, "ufl_id"),
-        #           "Invalid domain data, missing ufl_id() implementation.")
-
-        # Accept "everywhere", single subdomain, or multiple subdomains
-        ufl_assert(subdomain_id in ("everywhere",)
-                   or isinstance(subdomain_id, int)
-                   or (isinstance(subdomain_id, tuple)
-                       and all(isinstance(did, int) for did in subdomain_id)),
-                   "Invalid subdomain_id.")
+        # FIXME: Cannot require this (yet) because we currently have
+        # no way to implement ufl_id for dolfin SubDomain
+        # if not (self._subdomain_data is None or hasattr(self._subdomain_data, "ufl_id")):
+        #     error("Invalid domain data, missing ufl_id() implementation.")
+
+        # Accept "everywhere", single subdomain, or multiple
+        # subdomains
+        if isinstance(subdomain_id, tuple):
+            for did in subdomain_id:
+                if not isinstance(did, numbers.Integral):
+                    error("Invalid subdomain_id %s." % (did,))
+        else:
+            if not (subdomain_id in ("everywhere",)
+                    or isinstance(subdomain_id, numbers.Integral)):
+                error("Invalid subdomain_id %s." % (subdomain_id,))
         self._subdomain_id = subdomain_id
 
         # Validate compiler options are None or dict
-        ufl_assert(metadata is None or isinstance(metadata, dict),
-                   "Invalid metadata.")
+        if metadata is not None and not isinstance(metadata, dict):
+            error("Invalid metadata.")
         self._metadata = metadata or EmptyDict
 
     def integral_type(self):
@@ -170,9 +194,10 @@ class Measure(object):
         """
         return self._integral_type
 
-    def domain(self):
-        deprecate("Measure.domain() is deprecated, please use .ufl_domain() instead.")
-        return self.ufl_domain()
+    #def domain(self):
+    #    "Deprecated, please use .ufl_domain() instead."
+    #    deprecate("Measure.domain() is deprecated, please use .ufl_domain() instead.")
+    #    return self.ufl_domain()
 
     def ufl_domain(self):
         """Return the domain associated with this measure.
@@ -221,39 +246,58 @@ class Measure(object):
                        metadata=metadata, subdomain_data=subdomain_data)
 
     def subdomain_data(self):
-        """Return the integral subdomain_data. This data is not interpreted by UFL.
-        Its intension is to give a context in which the domain id is interpreted."""
+        """Return the integral subdomain_data. This data is not interpreted by
+        UFL.  Its intension is to give a context in which the domain
+        id is interpreted.
+
+        """
         return self._subdomain_data
 
-    # Note: Must keep the order of the first two arguments here (subdomain_id, metadata) for
-    # backwards compatibility, because some tutorials write e.g. dx(0, {...}) to set metadata.
-    def __call__(self, subdomain_id=None, metadata=None, domain=None, subdomain_data=None, degree=None, rule=None):
+    # Note: Must keep the order of the first two arguments here
+    # (subdomain_id, metadata) for backwards compatibility, because
+    # some tutorials write e.g. dx(0, {...}) to set metadata.
+    def __call__(self, subdomain_id=None, metadata=None, domain=None,
+                 subdomain_data=None, degree=None, scheme=None, rule=None):
         """Reconfigure measure with new domain specification or metadata."""
 
+        # Deprecation of 'rule' in favour of 'scheme'
+        if rule is not None:
+            deprecate("Measure argument 'rule' has been renamed to 'scheme'.")
+            assert scheme is None or scheme == rule
+            scheme = rule
+
         # Let syntax dx() mean integral over everywhere
-        all_args = (subdomain_id, metadata, domain, subdomain_data, degree, rule)
+        all_args = (subdomain_id, metadata, domain, subdomain_data,
+                    degree, scheme)
         if all(arg is None for arg in all_args):
             return self.reconstruct(subdomain_id="everywhere")
 
-        # Let syntax dx(domain) or dx(domain, metadata) mean integral over entire domain.
-        # To do this we need to hijack the first argument:
-        if subdomain_id is not None and (isinstance(subdomain_id, AbstractDomain) or hasattr(subdomain_id, 'ufl_domain')):
-            ufl_assert(domain is None, "Ambiguous: setting domain both as keyword argument and first argument.")
+        # Let syntax dx(domain) or dx(domain, metadata) mean integral
+        # over entire domain.  To do this we need to hijack the first
+        # argument:
+        if subdomain_id is not None and (isinstance(subdomain_id,
+                                                    AbstractDomain) or
+                                         hasattr(subdomain_id, 'ufl_domain')):
+            if domain is not None:
+                error("Ambiguous: setting domain both as keyword argument and first argument.")
             subdomain_id, domain = "everywhere", as_domain(subdomain_id)
 
-        # If degree or rule is set, inject into metadata. This is a quick fix to enable
-        # the dx(..., degree=3) notation. TODO: Make degree and rule properties of integrals.
-        if (degree, rule) != (None, None):
+        # If degree or scheme is set, inject into metadata. This is a
+        # quick fix to enable the dx(..., degree=3) notation.
+        # TODO: Make degree and scheme properties of integrals instead of adding to metadata.
+        if (degree, scheme) != (None, None):
             metadata = {} if metadata is None else metadata.copy()
             if degree is not None:
                 metadata["quadrature_degree"] = degree
-            if rule is not None:
-                metadata["quadrature_rule"] = rule
+            if scheme is not None:
+                metadata["quadrature_rule"] = scheme
 
         # If we get any keywords, use them to reconstruct Measure.
-        # Note that if only one argument is given, it is the subdomain_id,
-        # e.g. dx(3) == dx(subdomain_id=3)
-        return self.reconstruct(subdomain_id=subdomain_id, domain=domain, metadata=metadata, subdomain_data=subdomain_data)
+        # Note that if only one argument is given, it is the
+        # subdomain_id, e.g. dx(3) == dx(subdomain_id=3)
+        return self.reconstruct(subdomain_id=subdomain_id, domain=domain,
+                                metadata=metadata,
+                                subdomain_data=subdomain_data)
 
     def __getitem__(self, data):
         """This operator supports legacy syntax in python dolfin programs.
@@ -267,6 +311,10 @@ class Measure(object):
         deprecate("Notation dx[meshfunction] is deprecated. Please use dx(subdomain_data=meshfunction) instead.")
         return self(subdomain_data=data)
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         global integral_type_to_measure_name
         name = integral_type_to_measure_name[self._integral_type]
@@ -276,7 +324,7 @@ class Measure(object):
             args.append("subdomain_id=%s" % (self._subdomain_id,))
         if self._domain is not None:
             args.append("domain=%s" % (self._domain,))
-        if self._metadata: # Stored as EmptyDict if None
+        if self._metadata:  # Stored as EmptyDict if None
             args.append("metadata=%s" % (self._metadata,))
         if self._subdomain_data is not None:
             args.append("subdomain_data=%s" % (self._subdomain_data,))
@@ -286,21 +334,21 @@ class Measure(object):
     def __repr__(self):
         "Return a repr string for this Measure."
         global integral_type_to_measure_name
-        d = integral_type_to_measure_name[self._integral_type]
 
         args = []
         args.append(repr(self._integral_type))
 
         if self._subdomain_id is not None:
-            args.append("subdomain_id=%r" % (self._subdomain_id,))
+            args.append("subdomain_id=%s" % repr(self._subdomain_id))
         if self._domain is not None:
-            args.append("domain=%r" % (self._domain,))
-        if self._metadata: # Stored as EmptyDict if None
-            args.append("metadata=%r" % (self._metadata,))
+            args.append("domain=%s" % repr(self._domain))
+        if self._metadata:  # Stored as EmptyDict if None
+            args.append("metadata=%s" % repr(self._metadata))
         if self._subdomain_data is not None:
-            args.append("subdomain_data=%r" % (self._subdomain_data,))
+            args.append("subdomain_data=%s" % repr(self._subdomain_data))
 
-        return "%s(%s)" % (type(self).__name__, ', '.join(args))
+        r = "%s(%s)" % (type(self).__name__, ', '.join(args))
+        return as_native_str(r)
 
     def __hash__(self):
         "Return a hash value for this Measure."
@@ -313,12 +361,12 @@ class Measure(object):
 
     def __eq__(self, other):
         "Checks if two Measures are equal."
-        return (isinstance(other, Measure)
-                and self._integral_type == other._integral_type
-                and self._subdomain_id == other._subdomain_id
-                and self._domain == other._domain
-                and id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data)
-                and metadata_equal(self._metadata, other._metadata))
+        return (isinstance(other, Measure) and
+                self._integral_type == other._integral_type and
+                self._subdomain_id == other._subdomain_id and
+                self._domain == other._domain and
+                id_or_none(self._subdomain_data) == id_or_none(other._subdomain_data) and
+                metadata_equal(self._metadata, other._metadata))
 
     def __add__(self, other):
         """Add two measures (self+other).
@@ -351,13 +399,15 @@ class Measure(object):
             return NotImplemented
 
     def __rmul__(self, integrand):
-        """Multiply a scalar expression with measure to construct a form with a single integral.
+        """Multiply a scalar expression with measure to construct a form with
+a single integral.
 
         This is to implement the notation
 
             form = integrand * self
 
         Integration properties are taken from this Measure object.
+
         """
         # Avoid circular imports
         from ufl.integral import Integral
@@ -367,28 +417,30 @@ class Measure(object):
         if isinstance(integrand, (int, float)):
             integrand = as_ufl(integrand)
 
-        # Let other types implement multiplication with Measure
-        # if they want to (to support the dolfin-adjoint TimeMeasure)
+        # Let other types implement multiplication with Measure if
+        # they want to (to support the dolfin-adjoint TimeMeasure)
         if not isinstance(integrand, Expr):
             return NotImplemented
 
         # Allow only scalar integrands
         if not is_true_ufl_scalar(integrand):
-            msg = ("Can only integrate scalar expressions. The integrand is a " +
-                   "tensor expression with value rank %d and free indices %r.")
-            error(msg % (len(integrand.ufl_shape), integrand.ufl_free_indices))
+            error("Can only integrate scalar expressions. The integrand is a "
+                  "tensor expression with value shape %s and free indices with labels %s." %
+                    (integrand.ufl_shape, integrand.ufl_free_indices))
 
-        # If we have a tuple of domain ids, delegate composition to Integral.__add__:
+        # If we have a tuple of domain ids, delegate composition to
+        # Integral.__add__:
         subdomain_id = self.subdomain_id()
         if isinstance(subdomain_id, tuple):
             return sum(integrand*self.reconstruct(subdomain_id=d) for d in subdomain_id)
 
         # Check that we have an integer subdomain or a string
         # ("everywhere" or "otherwise", any more?)
-        ufl_assert(isinstance(subdomain_id, (int, str)),
-                   "Expecting integer or string domain id.")
+        if not isinstance(subdomain_id, string_types + (numbers.Integral,)):
+            error("Expecting integer or string domain id.")
 
-        # If we don't have an integration domain, try to find one in integrand
+        # If we don't have an integration domain, try to find one in
+        # integrand
         domain = self.ufl_domain()
         if domain is None:
             domains = extract_domains(integrand)
@@ -408,6 +460,8 @@ class Measure(object):
                             subdomain_data=self.subdomain_data())
         return Form([integral])
 
+
+# @six.python_2_unicode_compatible
 class MeasureSum(object):
     """Represents a sum of measures.
 
@@ -419,7 +473,8 @@ class MeasureSum(object):
 
         f*ds(1) + f*ds(3)
     """
-    __slots__ = ("_measures",)
+    __slots__ = as_native_strings(("_measures",))
+
     def __init__(self, *measures):
         self._measures = measures
 
@@ -434,9 +489,14 @@ class MeasureSum(object):
             return MeasureSum(*(self._measures + other._measures))
         return NotImplemented
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         return "{\n    " + "\n  + ".join(map(str, self._measures)) + "\n}"
 
+
 class MeasureProduct(object):
     """Represents a product of measures.
 
@@ -447,11 +507,13 @@ class MeasureProduct(object):
     This is work in progress and not functional. It needs support
     in other parts of ufl and the rest of the code generation chain.
     """
-    __slots__ = ("_measures",)
+    __slots__ = as_native_strings(("_measures",))
+
     def __init__(self, *measures):
         "Create MeasureProduct from given list of measures."
         self._measures = measures
-        ufl_assert(len(self._measures) > 1, "Expecting at least two measures.")
+        if len(self._measures) < 2:
+            error("Expecting at least two measures.")
 
     def __mul__(self, other):
         """Flatten multiplication of product measures.
diff --git a/ufl/objects.py b/ufl/objects.py
index dca0184..86de24f 100644
--- a/ufl/objects.py
+++ b/ufl/objects.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Utility objects for pretty syntax in user code."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -24,29 +24,28 @@
 from ufl.core.multiindex import indices
 from ufl.cell import Cell
 from ufl.measure import Measure
+from ufl.measure import integral_type_to_measure_name
 
 # Default indices
 i, j, k, l = indices(4)
 p, q, r, s = indices(4)
 
-# Default measures for integration
-from ufl.measure import integral_type_to_measure_name
 for integral_type, measure_name in integral_type_to_measure_name.items():
     globals()[measure_name] = Measure(integral_type)
-ds_tb = ds_b + ds_t # TODO: Firedrake hack, remove later
+
+# TODO: Firedrake hack, remove later
+ds_tb = ds_b + ds_t  # noqa: F821
 
 # Default measure dX including both uncut and cut cells
-dX = dx + dC
+dX = dx + dC  # noqa: F821
 
 # Create objects for builtin known cell types
-vertex        = Cell("vertex", 0)
-interval      = Cell("interval", 1)
-triangle      = Cell("triangle", 2)
-tetrahedron   = Cell("tetrahedron", 3)
+vertex = Cell("vertex", 0)
+interval = Cell("interval", 1)
+triangle = Cell("triangle", 2)
+tetrahedron = Cell("tetrahedron", 3)
 quadrilateral = Cell("quadrilateral", 2)
-hexahedron    = Cell("hexahedron", 3)
+hexahedron = Cell("hexahedron", 3)
 
 # Facet is just a dummy declaration for RestrictedElement
 facet = "facet"
-
-#__all__ = [] # FIXME:
diff --git a/ufl/operators.py b/ufl/operators.py
index 53b51b0..27ab33a 100644
--- a/ufl/operators.py
+++ b/ufl/operators.py
@@ -4,7 +4,7 @@ which are either already available as member functions on UFL objects
 or defined as compound operators involving basic operations on the UFL
 objects."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -22,13 +22,12 @@ objects."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
 # Modified by Kristian B. Oelgaard, 2011
+# Modified by Massimiliano Leoni, 2016.
 
 import operator
-from six.moves import map
 from six.moves import xrange as range
 
 from ufl.log import error, warning
-from ufl.assertions import ufl_assert
 from ufl.form import Form
 from ufl.constantvalue import Zero, ScalarValue, as_ufl
 from ufl.differentiation import VariableDerivative, Grad, Div, Curl, NablaGrad, NablaDiv
@@ -37,7 +36,7 @@ from ufl.tensoralgebra import Transposed, Inner, Outer, Dot, Cross, \
 from ufl.coefficient import Coefficient
 from ufl.variable import Variable
 from ufl.tensors import as_tensor, as_matrix, as_vector, ListTensor
-from ufl.conditional import EQ, NE, LE, GE, LT, GT, \
+from ufl.conditional import EQ, NE, \
     AndCondition, OrCondition, NotCondition, Conditional, MaxValue, MinValue
 from ufl.mathfunctions import Sqrt, Exp, Ln, Erf,\
     Cos, Sin, Tan, Cosh, Sinh, Tanh, Acos, Asin, Atan, Atan2,\
@@ -46,60 +45,71 @@ from ufl.restriction import CellAvg, FacetAvg
 from ufl.core.multiindex import indices
 from ufl.indexed import Indexed
 from ufl.geometry import SpatialCoordinate, FacetNormal
-from ufl.checks import is_globally_constant, is_cellwise_constant
+from ufl.checks import is_cellwise_constant
 from ufl.domain import extract_domains
 
-#--- Basic operators ---
+
+# --- Basic operators ---
 
 def rank(f):
-    "UFL operator: The rank of f."
+    "UFL operator: The rank of *f*."
     f = as_ufl(f)
     return len(f.ufl_shape)
 
+
 def shape(f):
-    "UFL operator: The shape of f."
+    "UFL operator: The shape of *f*."
     f = as_ufl(f)
     return f.ufl_shape
 
-#--- Elementwise tensor operators ---
+
+# --- Elementwise tensor operators ---
 
 def elem_op_items(op_ind, indices, *args):
     sh = args[0].ufl_shape
     indices = tuple(indices)
     n = sh[len(indices)]
+
     def extind(ii):
         return indices + (ii,)
+
     if len(sh) == len(indices)+1:
         return [op_ind(extind(i), *args) for i in range(n)]
     else:
         return [elem_op_items(op_ind, extind(i), *args) for i in range(n)]
 
+
 def elem_op(op, *args):
-    "UFL operator: Take the elementwise application of operator op on scalar values from one or more tensor arguments."
-    args = list(map(as_ufl, args))
+    "UFL operator: Take the elementwise application of operator *op* on scalar values from one or more tensor arguments."
+    args = [as_ufl(arg) for arg in args]
     sh = args[0].ufl_shape
-    ufl_assert(all(sh == x.ufl_shape for x in args),
-               "Cannot take elementwise operation with different shapes.")
+    if not all(sh == x.ufl_shape for x in args):
+        error("Cannot take elementwise operation with different shapes.")
+
     if sh == ():
         return op(*args)
+
     def op_ind(ind, *args):
         return op(*[x[ind] for x in args])
     return as_tensor(elem_op_items(op_ind, (), *args))
 
+
 def elem_mult(A, B):
-    "UFL operator: Take the elementwise multiplication of the tensors A and B with the same shape."
+    "UFL operator: Take the elementwise multiplication of tensors *A* and *B* with the same shape."
     return elem_op(operator.mul, A, B)
 
+
 def elem_div(A, B):
-    "UFL operator: Take the elementwise division of the tensors A and B with the same shape."
+    "UFL operator: Take the elementwise division of tensors *A* and *B* with the same shape."
     return elem_op(operator.truediv, A, B)
 
+
 def elem_pow(A, B):
-    "UFL operator: Take the elementwise power of the tensors A and B with the same shape."
+    "UFL operator: Take the elementwise power of tensors *A* and *B* with the same shape."
     return elem_op(operator.pow, A, B)
 
 
-#--- Tensor operators ---
+# --- Tensor operators ---
 
 def transpose(A):
     "UFL operator: Take the transposed of tensor A."
@@ -108,6 +118,7 @@ def transpose(A):
         return A
     return Transposed(A)
 
+
 def outer(*operands):
     "UFL operator: Take the outer product of two or more operands."
     n = len(operands)
@@ -124,35 +135,39 @@ def outer(*operands):
         return a*b
     return Outer(a, b)
 
+
 def inner(a, b):
-    "UFL operator: Take the inner product of a and b."
+    "UFL operator: Take the inner product of *a* and *b*."
     a = as_ufl(a)
     b = as_ufl(b)
     if a.ufl_shape == () and b.ufl_shape == ():
         return a*b
     return Inner(a, b)
 
-# TODO: Something like this would be useful in some cases,
-# but should inner just support len(a.ufl_shape) != len(b.ufl_shape) instead?
+
+# TODO: Something like this would be useful in some cases, but should
+# inner just support len(a.ufl_shape) != len(b.ufl_shape) instead?
 def _partial_inner(a, b):
     "UFL operator: Take the partial inner product of a and b."
     ar, br = len(a.ufl_shape), len(b.ufl_shape)
     n = min(ar, br)
     return contraction(a, list(range(n-ar, n-ar+n)), b, list(range(n)))
 
+
 def dot(a, b):
-    "UFL operator: Take the dot product of a and b."
+    "UFL operator: Take the dot product of *a* and *b*."
     a = as_ufl(a)
     b = as_ufl(b)
     if a.ufl_shape == () and b.ufl_shape == ():
         return a*b
     return Dot(a, b)
-    #return contraction(a, (len(a.ufl_shape)-1,), b, (len(b.ufl_shape)-1,))
+
 
 def contraction(a, a_axes, b, b_axes):
     "UFL operator: Take the contraction of a and b over given axes."
     ai, bi = a_axes, b_axes
-    ufl_assert(len(ai) == len(bi), "Contraction must be over the same number of axes.")
+    if len(ai) != len(bi):
+        error("Contraction must be over the same number of axes.")
     ash = a.ufl_shape
     bsh = b.ufl_shape
     aii = indices(len(a.ufl_shape))
@@ -164,55 +179,62 @@ def contraction(a, a_axes, b, b_axes):
         shape[i] = ash[j]
     for i, j in enumerate(bi):
         bii[j] = cii[i]
-        ufl_assert(shape[i] == bsh[j], "Shape mismatch in contraction.")
+        if shape[i] != bsh[j]:
+            error("Shape mismatch in contraction.")
     s = a[aii]*b[bii]
     cii = set(cii)
     ii = tuple(i for i in (aii + bii) if i not in cii)
     return as_tensor(s, ii)
 
+
 def perp(v):
-    "UFL operator: Take the perp of v, i.e. (-v1, +v0)."
+    "UFL operator: Take the perp of *v*, i.e. :math:`(-v_1, +v_0)`."
     v = as_ufl(v)
-    ufl_assert(v.ufl_shape == (2,), "Expecting a 2D vector expression.")
+    if v.ufl_shape != (2,):
+        error("Expecting a 2D vector expression.")
     return as_vector((-v[1], v[0]))
 
+
 def cross(a, b):
-    "UFL operator: Take the cross product of a and b."
+    "UFL operator: Take the cross product of *a* and *b*."
     a = as_ufl(a)
     b = as_ufl(b)
-    #ufl_assert(a.ufl_shape == (3,) and b.ufl_shape == (3,),
-    #           "Expecting 3D vectors in cross product.")
     return Cross(a, b)
 
+
 def det(A):
-    "UFL operator: Take the determinant of A."
+    "UFL operator: Take the determinant of *A*."
     A = as_ufl(A)
     if A.ufl_shape == ():
         return A
     return Determinant(A)
 
+
 def inv(A):
-    "UFL operator: Take the inverse of A."
+    "UFL operator: Take the inverse of *A*."
     A = as_ufl(A)
     if A.ufl_shape == ():
         return 1 / A
     return Inverse(A)
 
+
 def cofac(A):
-    "UFL operator: Take the cofactor of A."
+    "UFL operator: Take the cofactor of *A*."
     A = as_ufl(A)
     return Cofactor(A)
 
+
 def tr(A):
-    "UFL operator: Take the trace of A."
+    "UFL operator: Take the trace of *A*."
     A = as_ufl(A)
     return Trace(A)
 
+
 def diag(A):
-    """UFL operator: Take the diagonal part of rank 2 tensor A _or_
+    """UFL operator: Take the diagonal part of rank 2 tensor *A* **or**
     make a diagonal rank 2 tensor from a rank 1 tensor.
 
-    Always returns a rank 2 tensor. See also diag_vector."""
+    Always returns a rank 2 tensor. See also ``diag_vector``."""
 
     # TODO: Make a compound type or two for this operator
 
@@ -222,7 +244,8 @@ def diag(A):
         n, = A.ufl_shape
     elif r == 2:
         m, n = A.ufl_shape
-        ufl_assert(m == n, "Can only take diagonal of square tensors.")
+        if m != n:
+            error("Can only take diagonal of square tensors.")
     else:
         error("Expecting rank 1 or 2 tensor.")
 
@@ -234,61 +257,70 @@ def diag(A):
         rows.append(row)
     return as_matrix(rows)
 
+
 def diag_vector(A):
-    """UFL operator: Take the diagonal part of rank 2 tensor A and return as a vector.
+    """UFL operator: Take the diagonal part of rank 2 tensor *A* and return as a vector.
 
-    See also diag."""
+    See also ``diag``."""
 
     # TODO: Make a compound type for this operator
 
     # Get and check dimensions
-    ufl_assert(len(A.ufl_shape) == 2, "Expecting rank 2 tensor.")
+    if len(A.ufl_shape) != 2:
+        error("Expecting rank 2 tensor.")
     m, n = A.ufl_shape
-    ufl_assert(m == n, "Can only take diagonal of square tensors.")
+    if m != n:
+        error("Can only take diagonal of square tensors.")
 
     # Return diagonal vector
     return as_vector([A[i, i] for i in range(n)])
 
+
 def dev(A):
-    "UFL operator: Take the deviatoric part of A."
+    "UFL operator: Take the deviatoric part of *A*."
     A = as_ufl(A)
     return Deviatoric(A)
 
+
 def skew(A):
-    "UFL operator: Take the skew symmetric part of A."
+    "UFL operator: Take the skew symmetric part of *A*."
     A = as_ufl(A)
     return Skew(A)
 
+
 def sym(A):
-    "UFL operator: Take the symmetric part of A."
+    "UFL operator: Take the symmetric part of *A*."
     A = as_ufl(A)
     return Sym(A)
 
-#--- Differential operators
+
+# --- Differential operators
 
 def Dx(f, *i):
-    """UFL operator: Take the partial derivative of f with respect
-    to spatial variable number i. Equivalent to f.dx(\*i)."""
+    """UFL operator: Take the partial derivative of *f* with respect
+    to spatial variable number *i*. Equivalent to ``f.dx(*i)``."""
     f = as_ufl(f)
     return f.dx(*i)
 
+
 def Dt(f):
-    "UFL operator: <Not implemented yet!> The partial derivative of f with respect to time."
-    #return TimeDerivative(f) # TODO: Add class
+    "UFL operator: <Not implemented yet!> The partial derivative of *f* with respect to time."
     raise NotImplementedError
 
+
 def Dn(f):
-    """UFL operator: Take the directional derivative of f in the
+    """UFL operator: Take the directional derivative of *f* in the
     facet normal direction, Dn(f) := dot(grad(f), n)."""
     f = as_ufl(f)
     if is_cellwise_constant(f):
         return Zero(f.ufl_shape, f.ufl_free_indices, f.ufl_index_dimensions)
     return dot(grad(f), FacetNormal(f.ufl_domain()))
 
+
 def diff(f, v):
-    """UFL operator: Take the derivative of f with respect to the variable v.
+    """UFL operator: Take the derivative of *f* with respect to the variable *v*.
 
-    If f is a form, diff is applied to each integrand.
+    If *f* is a form, ``diff`` is applied to each integrand.
     """
     # Apply to integrands
     if isinstance(f, Form):
@@ -304,8 +336,9 @@ def diff(f, v):
     else:
         error("Expecting a Variable or SpatialCoordinate in diff.")
 
+
 def grad(f):
-    """UFL operator: Take the gradient of f.
+    """UFL operator: Take the gradient of *f*.
 
     This operator follows the grad convention where
 
@@ -323,8 +356,9 @@ def grad(f):
     f = as_ufl(f)
     return Grad(f)
 
+
 def div(f):
-    """UFL operator: Take the divergence of f.
+    """UFL operator: Take the divergence of *f*.
 
     This operator follows the div convention where
 
@@ -340,8 +374,9 @@ def div(f):
     f = as_ufl(f)
     return Div(f)
 
+
 def nabla_grad(f):
-    """UFL operator: Take the gradient of f.
+    """UFL operator: Take the gradient of *f*.
 
     This operator follows the grad convention where
 
@@ -359,8 +394,9 @@ def nabla_grad(f):
     f = as_ufl(f)
     return NablaGrad(f)
 
+
 def nabla_div(f):
-    """UFL operator: Take the divergence of f.
+    """UFL operator: Take the divergence of *f*.
 
     This operator follows the div convention where
 
@@ -376,16 +412,18 @@ def nabla_div(f):
     f = as_ufl(f)
     return NablaDiv(f)
 
+
 def curl(f):
-    "UFL operator: Take the curl of f."
+    "UFL operator: Take the curl of *f*."
     f = as_ufl(f)
     return Curl(f)
 rot = curl
 
-#--- DG operators ---
+
+# --- DG operators ---
 
 def jump(v, n=None):
-    "UFL operator: Take the jump of v across a facet."
+    "UFL operator: Take the jump of *v* across a facet."
     v = as_ufl(v)
     is_constant = len(extract_domains(v)) > 0
     if is_constant:
@@ -398,108 +436,133 @@ def jump(v, n=None):
             return dot(v('+'), n('+')) + dot(v('-'), n('-'))
     else:
         warning("Returning zero from jump of expression without a domain. This may be erroneous if a dolfin.Expression is involved.")
-        # FIXME: Is this right? If v has no domain, it doesn't depend on
-        # anything spatially variable or any form arguments, and thus
-        # the jump is zero. In other words, I'm assuming that
-        # "v has no geometric domains" is equivalent with "v is a spatial constant".
-        # Update: This is NOT true for jump(Expression("x[0]")) from dolfin.
+        # FIXME: Is this right? If v has no domain, it doesn't depend
+        # on anything spatially variable or any form arguments, and
+        # thus the jump is zero. In other words, I'm assuming that "v
+        # has no geometric domains" is equivalent with "v is a spatial
+        # constant".  Update: This is NOT true for
+        # jump(Expression("x[0]")) from dolfin.
         return Zero(v.ufl_shape, v.ufl_free_indices, v.ufl_index_dimensions)
 
+
 def avg(v):
-    "UFL operator: Take the average of v across a facet."
+    "UFL operator: Take the average of *v* across a facet."
     v = as_ufl(v)
     return 0.5*(v('+') + v('-'))
 
+
 def cell_avg(f):
-    "UFL operator: Take the average of v over a cell."
-    #ufl_assert((isinstance(f, Restricted) and isinstance(f.ufl_operands[0], FormArgument)) or
-    #    isinstance(f, FormArgument), "Can only take the cell average of a (optionally restricted) Coefficient or Argument.")
+    "UFL operator: Take the average of *v* over a cell."
     return CellAvg(f)
 
+
 def facet_avg(f):
-    "UFL operator: Take the average of v over a facet."
-    #ufl_assert((isinstance(f, Restricted) and isinstance(f.ufl_operands[0], FormArgument)) or
-    #    isinstance(f, FormArgument), "Can only take the cell average of a (optionally restricted) Coefficient or Argument.")
+    "UFL operator: Take the average of *v* over a facet."
     return FacetAvg(f)
 
-#--- Other operators ---
+
+# --- Other operators ---
 
 def variable(e):
-    "UFL operator: Define a variable representing the given expression, see also diff()."
+    """UFL operator: Define a variable representing the given expression, see also
+    ``diff()``."""
     e = as_ufl(e)
     return Variable(e)
 
-#--- Conditional expressions ---
+
+# --- Conditional expressions ---
 
 def conditional(condition, true_value, false_value):
-    """UFL operator: A conditional expression, taking the value of true_value
-    when condition evaluates to true and false_value otherwise."""
+    """UFL operator: A conditional expression, taking the value of *true_value*
+    when *condition* evaluates to ``true`` and *false_value* otherwise."""
     return Conditional(condition, true_value, false_value)
 
+
 def eq(left, right):
-    "UFL operator: A boolean expresion (left == right) for use with conditional."
+    """UFL operator: A boolean expression (left == right) for use with
+    ``conditional``."""
     return EQ(left, right)
 
+
 def ne(left, right):
-    "UFL operator: A boolean expresion (left != right) for use with conditional."
+    """UFL operator: A boolean expression (left != right) for use with
+    ``conditional``."""
     return NE(left, right)
 
+
 def le(left, right):
-    "UFL operator: A boolean expresion (left <= right) for use with conditional."
+    """UFL operator: A boolean expression (left <= right) for use with
+    ``conditional``."""
     return as_ufl(left) <= as_ufl(right)
 
+
 def ge(left, right):
-    "UFL operator: A boolean expresion (left >= right) for use with conditional."
+    """UFL operator: A boolean expression (left >= right) for use with
+    ``conditional``."""
     return as_ufl(left) >= as_ufl(right)
 
+
 def lt(left, right):
-    "UFL operator: A boolean expresion (left < right) for use with conditional."
+    """UFL operator: A boolean expression (left < right) for use with
+    ``conditional``."""
     return as_ufl(left) < as_ufl(right)
 
+
 def gt(left, right):
-    "UFL operator: A boolean expresion (left > right) for use with conditional."
+    """UFL operator: A boolean expression (left > right) for use with
+    ``conditional``."""
     return as_ufl(left) > as_ufl(right)
 
+
 def And(left, right):
-    "UFL operator: A boolean expresion (left and right) for use with conditional."
+    """UFL operator: A boolean expression (left and right) for use with
+    ``conditional``."""
     return AndCondition(left, right)
 
+
 def Or(left, right):
-    "UFL operator: A boolean expresion (left or right) for use with conditional."
+    """UFL operator: A boolean expression (left or right) for use with
+    ``conditional``."""
     return OrCondition(left, right)
 
+
 def Not(condition):
-    "UFL operator: A boolean expresion (not condition) for use with conditional."
+    """UFL operator: A boolean expression (not condition) for use with
+    ``conditional``."""
     return NotCondition(condition)
 
+
 def sign(x):
-    "UFL operator: Take the sign (+1 or -1) of x."
+    "UFL operator: Take the sign (+1 or -1) of *x*."
     # TODO: Add a Sign type for this?
     return conditional(eq(x, 0), 0, conditional(lt(x, 0), -1, +1))
 
+
 def max_value(x, y):
-    "UFL operator: Take the maximum of x and y."
+    "UFL operator: Take the maximum of *x* and *y*."
     x = as_ufl(x)
     y = as_ufl(y)
     return MaxValue(x, y)
 
+
 def min_value(x, y):
-    "UFL operator: Take the minimum of x and y."
+    "UFL operator: Take the minimum of *x* and *y*."
     x = as_ufl(x)
     y = as_ufl(y)
     return MinValue(x, y)
 
-def Max(x, y): # TODO: Deprecate this notation?
-    "UFL operator: Take the maximum of x and y."
-    #return conditional(gt(x, y), x, y)
+
+def Max(x, y):  # TODO: Deprecate this notation?
+    "UFL operator: Take the maximum of *x* and *y*."
     return max_value(x, y)
 
-def Min(x, y): # TODO: Deprecate this notation?
-    "UFL operator: Take the minimum of x and y."
-    #return conditional(lt(x, y), x, y)
+
+def Min(x, y):  # TODO: Deprecate this notation?
+    "UFL operator: Take the minimum of *x* and *y*."
     return min_value(x, y)
 
-#--- Math functions ---
+
+# --- Math functions ---
 
 def _mathfunction(f, cls):
     f = as_ufl(f)
@@ -508,56 +571,69 @@ def _mathfunction(f, cls):
         return float(r)
     return r
 
+
 def sqrt(f):
-    "UFL operator: Take the square root of f."
+    "UFL operator: Take the square root of *f*."
     return _mathfunction(f, Sqrt)
 
+
 def exp(f):
-    "UFL operator: Take the exponential of f."
+    "UFL operator: Take the exponential of *f*."
     return _mathfunction(f, Exp)
 
+
 def ln(f):
-    "UFL operator: Take the natural logarithm of f."
+    "UFL operator: Take the natural logarithm of *f*."
     return _mathfunction(f, Ln)
 
+
 def cos(f):
-    "UFL operator: Take the cosinus of f."
+    "UFL operator: Take the cosine of *f*."
     return _mathfunction(f, Cos)
 
+
 def sin(f):
-    "UFL operator: Take the sinus of f."
+    "UFL operator: Take the sine of *f*."
     return _mathfunction(f, Sin)
 
+
 def tan(f):
-    "UFL operator: Take the tangent of f."
+    "UFL operator: Take the tangent of *f*."
     return _mathfunction(f, Tan)
 
+
 def cosh(f):
-    "UFL operator: Take the cosinus hyperbolicus of f."
+    "UFL operator: Take the hyperbolic cosine of *f*."
     return _mathfunction(f, Cosh)
 
+
 def sinh(f):
-    "UFL operator: Take the sinus hyperbolicus of f."
+    "UFL operator: Take the hyperbolic sine of *f*."
     return _mathfunction(f, Sinh)
 
+
 def tanh(f):
-    "UFL operator: Take the tangent hyperbolicus of f."
+    "UFL operator: Take the hyperbolic tangent of *f*."
     return _mathfunction(f, Tanh)
 
+
 def acos(f):
-    "UFL operator: Take the inverse cosinus of f."
+    "UFL operator: Take the inverse cosine of *f*."
     return _mathfunction(f, Acos)
 
+
 def asin(f):
-    "UFL operator: Take the inverse sinus of f."
+    "UFL operator: Take the inverse sine of *f*."
     return _mathfunction(f, Asin)
 
+
 def atan(f):
-    "UFL operator: Take the inverse tangent of f."
+    "UFL operator: Take the inverse tangent of *f*."
     return _mathfunction(f, Atan)
 
+
 def atan_2(f1, f2):
-    "UFL operator: Take the inverse tangent of f."
+    "UFL operator: Take the inverse tangent with two the arguments *f1* and *f2*."
     f1 = as_ufl(f1)
     f2 = as_ufl(f2)
     r = Atan2(f1, f2)
@@ -565,28 +641,33 @@ def atan_2(f1, f2):
         return float(r)
     return r
 
+
 def erf(f):
-    "UFL operator: Take the error function of f."
+    "UFL operator: Take the error function of *f*."
     return _mathfunction(f, Erf)
 
+
 def bessel_J(nu, f):
     """UFL operator: cylindrical Bessel function of the first kind."""
     nu = as_ufl(nu)
     f = as_ufl(f)
     return BesselJ(nu, f)
 
+
 def bessel_Y(nu, f):
     """UFL operator: cylindrical Bessel function of the second kind."""
     nu = as_ufl(nu)
     f = as_ufl(f)
     return BesselY(nu, f)
 
+
 def bessel_I(nu, f):
     """UFL operator: regular modified cylindrical Bessel function."""
     nu = as_ufl(nu)
     f = as_ufl(f)
     return BesselI(nu, f)
 
+
 def bessel_K(nu, f):
     """UFL operator: irregular modified cylindrical Bessel function."""
     nu = as_ufl(nu)
@@ -594,16 +675,16 @@ def bessel_K(nu, f):
     return BesselK(nu, f)
 
 
-#--- Special function for exterior_derivative
+# --- Special function for exterior_derivative
 
 def exterior_derivative(f):
-    """UFL operator: Take the exterior derivative of f.
+    """UFL operator: Take the exterior derivative of *f*.
 
     The exterior derivative uses the element family to
-    determine whether id, grad, curl or div should be used.
+    determine whether ``id``, ``grad``, ``curl`` or ``div`` should be used.
 
-    Note that this uses the 'grad' and 'div' operators,
-    as opposed to 'nabla_grad' and 'nabla_div'.
+    Note that this uses the ``grad`` and ``div`` operators,
+    as opposed to ``nabla_grad`` and ``nabla_div``.
     """
 
     # Extract the element from the input f
@@ -616,7 +697,7 @@ def exterior_derivative(f):
         element = element.extract_component(index)[1]
     elif isinstance(f, ListTensor):
         f0 = f.ufl_operands[0]
-        f0expr, f0indices = f0.ufl_operands # FIXME: Assumption on type of f0!!!
+        f0expr, f0indices = f0.ufl_operands  # FIXME: Assumption on type of f0!!!
         if len(f0indices) > 1:
             raise NotImplementedError
         index = int(f0indices[0])
diff --git a/ufl/permutation.py b/ufl/permutation.py
index 5e4d545..5728801 100644
--- a/ufl/permutation.py
+++ b/ufl/permutation.py
@@ -2,7 +2,7 @@
 """This module provides utility functions for computing permutations
 and generating index lists."""
 
-# Copyright (C) 2008-2015 Anders Logg and Kent-Andre Mardal
+# Copyright (C) 2008-2016 Anders Logg and Kent-Andre Mardal
 #
 # This file is part of UFL.
 #
@@ -19,10 +19,11 @@ and generating index lists."""
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 #
-# Modified by Martin Alnæs 2009-2015
+# Modified by Martin Alnæs 2009-2016
 
 from six.moves import xrange as range
 
+
 def compute_indices(shape):
     "Compute all index combinations for given shape"
     if len(shape) == 0:
@@ -34,18 +35,22 @@ def compute_indices(shape):
             indices.append((i,) + sub_index)
     return tuple(indices)
 
+
 # functional version:
 def compute_indices2(shape):
     "Compute all index combinations for given shape"
     return ((),) if len(shape) == 0 else tuple((i,) + sub_index for i in range(shape[0]) for sub_index in compute_indices2(shape[1:]))
 
+
 def build_component_numbering(shape, symmetry):
     """Build a numbering of components within the given value shape,
     taking into consideration a symmetry mapping which leaves the
     mapping noncontiguous. Returns a dict { component -> numbering }
-    and an ordered list of components [ numbering -> component ].
-    The dict contains all components while the list only contains
-    the ones not mapped by the symmetry mapping."""
+    and an ordered list of components [ numbering -> component ].  The
+    dict contains all components while the list only contains the ones
+    not mapped by the symmetry mapping.
+
+    """
     vi2si, si2vi = {}, []
     indices = compute_indices(shape)
     # Number components not in symmetry mapping
@@ -62,9 +67,12 @@ def build_component_numbering(shape, symmetry):
         assert vi2si[c] == k
     return vi2si, si2vi
 
-def compute_permutations(k, n, skip = None):
+
+def compute_permutations(k, n, skip=None):
     """Compute all permutations of k elements from (0, n) in rising order.
-    Any elements that are contained in the list skip are not included."""
+    Any elements that are contained in the list skip are not included.
+
+    """
     if k == 0:
         return []
     if skip is None:
@@ -81,9 +89,12 @@ def compute_permutations(k, n, skip = None):
                 permutations.append((i,) + p)
     return permutations
 
+
 def compute_permutation_pairs(j, k):
-    """Compute all permutations of j + k elements from (0, j + k) in rising
-    order within (0, j) and (j, j + k) respectively."""
+    """Compute all permutations of j + k elements from (0, j + k) in
+    rising order within (0, j) and (j, j + k) respectively.
+
+    """
     permutations = []
     pp0 = compute_permutations(j, j + k)
     for p0 in pp0:
@@ -92,6 +103,7 @@ def compute_permutation_pairs(j, k):
             permutations.append((p0, p1))
     return permutations
 
+
 def compute_sign(permutation):
     "Compute sign by sorting."
     sign = 1
@@ -106,6 +118,7 @@ def compute_sign(permutation):
                 return 0
     return sign
 
+
 def compute_order_tuples(k, n):
     "Compute all tuples of n integers such that the sum is k"
     if n == 1:
diff --git a/ufl/precedence.py b/ufl/precedence.py
index e10492d..c7de876 100644
--- a/ufl/precedence.py
+++ b/ufl/precedence.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Precedence handling."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,38 +21,41 @@
 from ufl.log import warning
 from six import iteritems
 
+
 # FIXME: This code is crap...
 
 def parstr(child, parent, pre="(", post=")", format=str):
-    # Execute when needed instead of on import,
-    # which leads to all kinds of circular trouble.
-    # Fixing this could be an optimization of str(expr) though.
+    # Execute when needed instead of on import, which leads to all
+    # kinds of circular trouble.  Fixing this could be an optimization
+    # of str(expr) though.
     if not hasattr(parent, '_precedence'):
         assign_precedences(build_precedence_list())
 
-    # We want child to be evaluated fully first,
-    # and if the parent has higher precedence
-    # we later wrap in ().
+    # We want child to be evaluated fully first, and if the parent has
+    # higher precedence we later wrap in ().
     s = format(child)
 
-    # Operators where operands are always parenthesized because precedence is not defined below
+    # Operators where operands are always parenthesized because
+    # precedence is not defined below
     if parent._precedence == 0:
         return pre + s + post
 
-    # If parent operator binds stronger than child, must parenthesize child
+    # If parent operator binds stronger than child, must parenthesize
+    # child
     # FIXME: Is this correct for all possible positions of () in a + b + c?
     # FIXME: Left-right rule
-    if parent._precedence > child._precedence: # parent = indexed, child = terminal
+    if parent._precedence > child._precedence:  # parent = indexed, child = terminal
         return pre + s + post
 
     # Nothing needed
     return s
 
+
 def build_precedence_list():
     from ufl.classes import Operator, Terminal, Sum, IndexSum, Product, Division, Power, MathFunction, BesselFunction, Abs, Indexed
 
     # TODO: Fill in other types...
-    #Power <= Transposed
+    # Power <= Transposed
 
     precedence_list = []
     # Default operator behaviour: should always add parentheses
@@ -60,7 +63,8 @@ def build_precedence_list():
 
     precedence_list.append((Sum,))
 
-    # sum_i a + b = (sum_i a) + b != sum_i (a + b), sum_i binds stronger than +, but weaker than product
+    # sum_i a + b = (sum_i a) + b != sum_i (a + b), sum_i binds
+    # stronger than +, but weaker than product
     precedence_list.append((IndexSum,))
 
     precedence_list.append((Product, Division,))
@@ -74,6 +78,7 @@ def build_precedence_list():
     precedence_list.append((Terminal,))
     return precedence_list
 
+
 def build_precedence_mapping(precedence_list):
     """Given a precedence list, build a dict with class->int mappings.
     Utility function used by some external code.
@@ -100,6 +105,7 @@ def build_precedence_mapping(precedence_list):
                 missing.add(c)
     return pm, missing
 
+
 def assign_precedences(precedence_list):
     "Given a precedence list, assign ints to class._precedence."
     pm, missing = build_precedence_mapping(precedence_list)
diff --git a/ufl/protocols.py b/ufl/protocols.py
index d26f519..30088ce 100644
--- a/ufl/protocols.py
+++ b/ufl/protocols.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -16,6 +16,7 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+
 def id_or_none(obj):
     """Returns None if the object is None, obj.ufl_id() if available, or id(obj) if not.
 
@@ -28,12 +29,13 @@ def id_or_none(obj):
     elif hasattr(obj, 'ufl_id'):
         return obj.ufl_id()
     else:
-        #warning("Expecting an object implementing the ufl_id function.") # TODO: Can we enable this? Not sure about meshfunctions etc in dolfin.
         return id(obj)
 
+
 def metadata_equal(a, b):
     return (sorted((k, id(v)) for k, v in list(a.items())) ==
             sorted((k, id(v)) for k, v in list(b.items())))
 
+
 def metadata_hashdata(md):
     return tuple(sorted((k, id(v)) for k, v in list(md.items())))
diff --git a/ufl/referencevalue.py b/ufl/referencevalue.py
index beb304f..92b0184 100644
--- a/ufl/referencevalue.py
+++ b/ufl/referencevalue.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Representation of the reference value of a function."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -22,7 +22,7 @@ from ufl.core.ufl_type import ufl_type
 from ufl.core.operator import Operator
 from ufl.core.terminal import FormArgument
 from ufl.log import error
-from ufl.assertions import ufl_assert
+
 
 @ufl_type(num_ops=1,
           is_index_free=True,
@@ -33,7 +33,8 @@ class ReferenceValue(Operator):
     __slots__ = ()
 
     def __init__(self, f):
-        ufl_assert(isinstance(f, FormArgument), "Can only take reference value of form arguments.")
+        if not isinstance(f, FormArgument):
+            error("Can only take reference value of form arguments.")
         Operator.__init__(self, (f,))
 
     @property
@@ -46,6 +47,3 @@ class ReferenceValue(Operator):
 
     def __str__(self):
         return "reference_value(%s)" % self.ufl_operands[0]
-
-    def __repr__(self):
-        return "ReferenceValue(%r)" % self.ufl_operands[0]
diff --git a/ufl/restriction.py b/ufl/restriction.py
index 89a9df8..f7eb598 100644
--- a/ufl/restriction.py
+++ b/ufl/restriction.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Restriction operations."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,12 +18,12 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
-from ufl.log import error
 from ufl.core.operator import Operator
 from ufl.precedence import parstr
 from ufl.core.ufl_type import ufl_type
 
-#--- Restriction operators ---
+
+# --- Restriction operators ---
 
 @ufl_type(is_abstract=True,
           num_ops=1,
@@ -42,19 +42,19 @@ class Restricted(Operator):
         return self._side
 
     def evaluate(self, x, mapping, component, index_values):
-        return self.ufl_operands[0].evaluate(x, mapping, component, index_values)
+        return self.ufl_operands[0].evaluate(x, mapping, component,
+                                             index_values)
 
     def __str__(self):
         return "%s('%s')" % (parstr(self.ufl_operands[0], self), self._side)
 
-    def __repr__(self):
-        return "%s(%r)" % (self._ufl_class_.__name__, self.ufl_operands[0])
 
 @ufl_type(is_terminal_modifier=True)
 class PositiveRestricted(Restricted):
     __slots__ = ()
     _side = "+"
 
+
 @ufl_type(is_terminal_modifier=True)
 class NegativeRestricted(Restricted):
     __slots__ = ()
@@ -80,14 +80,12 @@ class CellAvg(Operator):
 
     def evaluate(self, x, mapping, component, index_values):
         "Performs an approximate symbolic evaluation, since we dont have a cell."
-        return self.ufl_operands[0].evaluate(x, mapping, component, index_values)
+        return self.ufl_operands[0].evaluate(x, mapping, component,
+                                             index_values)
 
     def __str__(self):
         return "cell_avg(%s)" % (self.ufl_operands[0],)
 
-    def __repr__(self):
-        return "CellAvg(%r)" % self.ufl_operands[0]
-
 
 # TODO: Place in a better file?
 @ufl_type(is_index_free=True,
@@ -112,6 +110,3 @@ class FacetAvg(Operator):
 
     def __str__(self):
         return "facet_avg(%s)" % (self.ufl_operands[0],)
-
-    def __repr__(self):
-        return "FacetAvg(%r)" % self.ufl_operands[0]
diff --git a/ufl/sobolevspace.py b/ufl/sobolevspace.py
index 1f4352e..1360b55 100644
--- a/ufl/sobolevspace.py
+++ b/ufl/sobolevspace.py
@@ -24,6 +24,11 @@ symbolic reasoning about the spaces in which finite elements lie."""
 # Modified by Martin Alnaes 2014
 # Modified by Lizao Li 2015
 
+#import six
+from ufl.utils.py23 import as_native_str
+
+
+# @six.python_2_unicode_compatible
 class SobolevSpace(object):
     """Symbolic representation of a Sobolev space. This implements a
     subset of the methods of a Python set so that finite elements and
@@ -42,11 +47,16 @@ class SobolevSpace(object):
         # Ensure that the inclusion operations are transitive.
         self.parents = p.union(*[p_.parents for p_ in p])
 
+    def __unicode__(self):
+        # Only in python 2
+        return str(self).decode("utf-8")
+
     def __str__(self):
         return self.name
 
     def __repr__(self):
-        return "SobolevSpace(%r, %r)" % (self.name, list(self.parents))
+        r = "SobolevSpace(%s, %s)" % (repr(self.name), repr(list(self.parents)))
+        return as_native_str(r)
 
     def _repr_latex_(self):
         if len(self.name) == 2:
@@ -71,8 +81,8 @@ class SobolevSpace(object):
             raise TypeError("Unable to test for inclusion of a " +
                             "SobolevSpace in another SobolevSpace. " +
                             "Did you mean to use <= instead?")
-        return (other.sobolev_space() == self
-                or self in other.sobolev_space().parents)
+        return (other.sobolev_space() == self or
+                self in other.sobolev_space().parents)
 
     def __lt__(self, other):
         """In common with intrinsic Python sets, < indicates "is a proper
@@ -104,9 +114,11 @@ class SobolevSpace(object):
             return HCurlElement(element)
         raise NotImplementedError("SobolevSpace has no call operator (only the specific HDiv and HCurl instances).")
 
+
 L2 = SobolevSpace("L2")
 HDiv = SobolevSpace("HDiv", [L2])
 HCurl = SobolevSpace("HCurl", [L2])
 H1 = SobolevSpace("H1", [HDiv, HCurl, L2])
 H2 = SobolevSpace("H2", [H1])
 HEin = SobolevSpace("HEin", [L2])
+HDivDiv = SobolevSpace("HDivDiv", [L2])
diff --git a/ufl/sorting.py b/ufl/sorting.py
index 42c9a79..335cf76 100644
--- a/ufl/sorting.py
+++ b/ufl/sorting.py
@@ -2,7 +2,7 @@
 """This module contains a sorting rule for expr objects that
 is more robust w.r.t. argument numbering than using repr."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -24,138 +24,96 @@ is more robust w.r.t. argument numbering than using repr."""
 
 from six.moves import zip
 
-from ufl.log import error
-from ufl.core.terminal import Terminal
+from functools import cmp_to_key
+
+from ufl.core.expr import Expr
 from ufl.argument import Argument
 from ufl.coefficient import Coefficient
-from ufl.core.multiindex import Index, FixedIndex, MultiIndex
+from ufl.core.multiindex import FixedIndex, MultiIndex
 from ufl.variable import Label
 
 
-def _cmp3(a, b):
-    "Replacement for cmp(), removed in Python 3."
-    return -1 if (a < b) else (+1 if a > b else 0)
-
-
-def _cmp_terminal(a, b):
-    # Is it a...
-    # ... MultiIndex? Careful not to depend on Index.count() here! This is placed first because it is most frequent.
-    if isinstance(a, MultiIndex):
-        # Make decision based on the first index pair possible
-        for i, j in zip(a._indices, b._indices):
-            fix1 = isinstance(i, FixedIndex)
-            fix2 = isinstance(j, FixedIndex)
-            if fix1 and fix2:
-                # Both are FixedIndex, sort by value
-                x, y = i._value, j._value
-                if x < y:
-                    return -1
-                elif x > y:
-                    return +1
-                else:
-                    # Same value, no decision
-                    continue
-            elif fix1:
-                # Sort fixed before free
+def _cmp_multi_index(a, b):
+    # Careful not to depend on Index.count() here!
+    # This is placed first because it is most frequent.
+    # Make decision based on the first index pair possible
+    for i, j in zip(a._indices, b._indices):
+        fix1 = isinstance(i, FixedIndex)
+        fix2 = isinstance(j, FixedIndex)
+        if fix1 and fix2:
+            # Both are FixedIndex, sort by value
+            x, y = i._value, j._value
+            if x < y:
                 return -1
-            elif fix2:
-                # Sort fixed before free
+            elif x > y:
                 return +1
             else:
-                # Both are Index, no decision, do not depend on count!
-                pass
-        # Failed to make a decision, return 0 by default
-        # (this does not mean equality, it could be e.g.
-        # [i,0] vs [j,0] because the counts of i,j cannot be used)
-        return 0
-
-    # ... Label object?
-    elif isinstance(a, Label):
-        # Don't compare counts! Causes circular problems when renumbering to get a canonical form.
-        # Therefore, even though a and b are not equal in general (__eq__ won't be True),
-        # but for this sorting they are considered equal and we return 0.
-        return 0
-
-    # ... Coefficient?
-    elif isinstance(a, Coefficient):
-        # It's ok to compare relative counts for Coefficients,
-        # since their ordering is a property of the form
-        x, y = a._count, b._count
-        if x < y:
-            return -1
-        elif x > y:
-            return +1
-        else:
-            return 0
-
-    # ... Argument?
-    elif isinstance(a, Argument):
-        # It's ok to compare relative number and part for Arguments,
-        # since their ordering is a property of the form
-        x = (a._number, a._part)
-        y = (b._number, b._part)
-        if x < y:
+                # Same value, no decision
+                continue
+        elif fix1:
+            # Sort fixed before free
             return -1
-        elif x > y:
+        elif fix2:
+            # Sort fixed before free
             return +1
         else:
-            return 0
+            # Both are Index, no decision, do not depend on count!
+            pass
+    # Failed to make a decision, return 0 by default
+    # (this does not mean equality, it could be e.g.
+    # [i,0] vs [j,0] because the counts of i,j cannot be used)
+    return 0
 
-    # ... another kind of Terminal object?
-    else:
-        # The cost of repr on a terminal is fairly small, and bounded
-        x, y = repr(a), repr(b)
-        if x < y:
-            return -1
-        elif x > y:
-            return +1
-        else:
-            return 0
 
+def _cmp_label(a, b):
+    # Don't compare counts! Causes circular problems when renumbering to get a canonical form.
+    # Therefore, even though a and b are not equal in general (__eq__ won't be True),
+    # but for this sorting they are considered equal and we return 0.
+    return 0
 
-def _cmp_operator(a, b):
-    # If the hash is the same, assume equal for the purpose of sorting.
-    # This introduces a minor chance of nondeterministic behaviour, just as with MultiIndex.
-    # Although collected statistics for complicated forms suggest that the hash
-    # function is pretty good so there shouldn't be collisions.
-    if hash(a) == hash(b): # FIXME: Test this for performance improvement.
-        return 0
 
-    aops = a.ufl_operands
-    bops = b.ufl_operands
+def _cmp_coefficient(a, b):
+    # It's ok to compare relative counts for Coefficients,
+    # since their ordering is a property of the form
+    x, y = a._count, b._count
+    if x < y:
+        return -1
+    elif x > y:
+        return +1
+    else:
+        return 0
 
-    # Sort by children in natural order
-    for (r, s) in zip(aops, bops):
-        # Ouch! This becomes worst case O(n) then?
-        # FIXME: Perhaps replace with comparison of hash value? But that's not stable between python versions.
-        c = cmp_expr(r, s)
-        if c:
-            return c
 
-    # All children compare as equal, a and b must be equal. Except for...
-    # A few type, notably ExprList and ExprMapping, can have a different number of operands.
-    # Sort by the length if it's different. Doing this after sorting by children because
-    # these types are rare so we try to avoid the cost of this check for most nodes.
-    return _cmp3(len(aops), len(bops))
+def _cmp_argument(a, b):
+    # It's ok to compare relative number and part for Arguments,
+    # since their ordering is a property of the form
+    x = (a._number, a._part)
+    y = (b._number, b._part)
+    if x < y:
+        return -1
+    elif x > y:
+        return +1
+    else:
+        return 0
 
 
-def cmp_expr2(a, b):
-    "Sorting rule for Expr objects. NB! Do not use to compare for equality!"
+def _cmp_terminal_by_repr(a, b):
+    # The cost of repr on a terminal is fairly small, and bounded
+    x = repr(a)
+    y = repr(b)
+    return -1 if x < y else (0 if x == y else +1)
 
-    # First sort quickly by type code
-    c = _cmp3(a._ufl_typecode_, b._ufl_typecode_)
-    if c:
-        return c
 
-    # Now we know that the type is the same, check further based on type specific properties.
-    if a._ufl_is_terminal_:
-        return _cmp_terminal(a, b)
-    else:
-        return _cmp_operator(a, b)
+# Hack up a MultiFunction-like type dispatch for terminal comparisons
+_terminal_cmps = [_cmp_terminal_by_repr]*Expr._ufl_num_typecodes_
+_terminal_cmps[MultiIndex._ufl_typecode_] = _cmp_multi_index
+_terminal_cmps[Argument._ufl_typecode_] = _cmp_argument
+_terminal_cmps[Coefficient._ufl_typecode_] = _cmp_coefficient
+_terminal_cmps[Label._ufl_typecode_] = _cmp_label
 
 
-# FIXME: Test and benchmark this! Could be faster since it avoids the recursion.
 def cmp_expr(a, b):
+    "Replacement for cmp(a, b), removed in Python 3, for Expr objects."
 
     # Modelled after pre_traversal to avoid recursion:
     left = [(a, b)]
@@ -164,22 +122,23 @@ def cmp_expr(a, b):
 
         # First sort quickly by type code
         x, y = a._ufl_typecode_, b._ufl_typecode_
-        if x < y:
-            return -1
-        elif x > y:
-            return +1
+        if x != y:
+            return -1 if x < y else +1
 
-        # Now we know that the type is the same, check further based on type specific properties.
+        # Now we know that the type is the same, check further based
+        # on type specific properties.
         if a._ufl_is_terminal_:
-            c = _cmp_terminal(a, b)
+            c = _terminal_cmps[x](a, b)
             if c:
                 return c
         else:
-            # If the hash is the same, assume equal for the purpose of sorting.
-            # This introduces a minor chance of nondeterministic behaviour, just as with MultiIndex.
-            # Although collected statistics for complicated forms suggest that the hash
-            # function is pretty good so there shouldn't be collisions.
-            #if hash(a) == hash(b): # FIXME: Test this for performance improvement.
+            # If the hash is the same, assume equal for the purpose of
+            # sorting.  This introduces a minor chance of
+            # nondeterministic behaviour, just as with MultiIndex.
+            # Although collected statistics for complicated forms
+            # suggest that the hash function is pretty good so there
+            # shouldn't be collisions.
+            # if hash(a) == hash(b): # FIXME: Test this for performance improvement.
             #    return 0
 
             # Delve into subtrees
@@ -194,41 +153,27 @@ def cmp_expr(a, b):
                 # Append subtree for further inspection
                 left.append((r, s))
 
-            # All children compare as equal, a and b must be equal. Except for...
-            # A few type, notably ExprList and ExprMapping, can have a different number of operands.
-            # Sort by the length if it's different. Doing this after sorting by children because
-            # these types are rare so we try to avoid the cost of this check for most nodes.
+            # All children compare as equal, a and b must be
+            # equal. Except for...  A few types, notably ExprList and
+            # ExprMapping, can have a different number of operands.
+            # Sort by the length if it's different. Doing this after
+            # sorting by children because these types are rare so we
+            # try to avoid the cost of this check for most nodes.
             x, y = len(aops), len(bops)
-            if x < y:
-                return -1
-            elif x > y:
-                return +1
+            if x != y:
+                return -1 if x < y else +1
 
     # Equal if we get out of the above loop!
     return 0
 
 
-
-# Not in python 2.6...
-#from functools import cmp_to_key
-
-
-class ExprKey(object):
-    __slots__ = ('x',)
-
-    def __init__(self, x):
-        self.x = x
-
-    def __lt__(self, other):
-        return cmp_expr(self.x, other.x) < 0
-
-
-def sorted_expr(seq):
-    return sorted(seq, key=ExprKey)
+def sorted_expr(sequence):
+    "Return a canonically sorted list of Expr objects in sequence."
+    return sorted(sequence, key=cmp_to_key(cmp_expr))
 
 
 def sorted_expr_sum(seq):
-    seq2 = sorted(seq, key=ExprKey)
+    seq2 = sorted(seq, key=cmp_to_key(cmp_expr))
     s = seq2[0]
     for e in seq2[1:]:
         s = s + e
diff --git a/ufl/split_functions.py b/ufl/split_functions.py
index 55c81db..298b943 100644
--- a/ufl/split_functions.py
+++ b/ufl/split_functions.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Algorithm for splitting a Coefficient or Argument into subfunctions."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -23,104 +23,102 @@
 from six.moves import xrange as range
 
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.utils.sequences import product
-from ufl.utils.dicts import EmptyDict
 from ufl.finiteelement import MixedElement, TensorElement
-from ufl.tensors import as_vector, as_matrix, as_tensor
+from ufl.tensors import as_vector, as_matrix, ListTensor
+from ufl.indexed import Indexed
+from ufl.permutation import compute_indices
+from ufl.utils.indexflattening import flatten_multiindex, shape_to_strides
 
 
 def split(v):
     """UFL operator: If v is a Coefficient or Argument in a mixed space, returns
     a tuple with the function components corresponding to the subelements."""
+
+    # Default range is all of v
+    begin = 0
+    end = None
+
+    if isinstance(v, Indexed):
+        # Special case: split previous output of split again
+        # Consistent with simple element, just return function in a tuple
+        return (v,)
+
+    elif isinstance(v, ListTensor):
+        # Special case: split previous output of split again
+        ops = v.ufl_operands
+        if all(isinstance(comp, Indexed) for comp in ops):
+            args = [comp.ufl_operands[0] for comp in ops]
+            if all(args[0] == args[i] for i in range(1, len(args))):
+                # Get innermost terminal here and its element
+                v = args[0]
+                # Get relevant range of v components
+                begin, = ops[0].ufl_operands[1]
+                end, = ops[-1].ufl_operands[1]
+                begin = int(begin)
+                end = int(end) + 1
+            else:
+                error("Don't know how to split %s." % (v,))
+        else:
+            error("Don't know how to split %s." % (v,))
+
     # Special case: simple element, just return function in a tuple
     element = v.ufl_element()
     if not isinstance(element, MixedElement):
+        assert end is None
         return (v,)
 
     if isinstance(element, TensorElement):
-        s = element.symmetry()
-        if s:
-            # FIXME: How should this be defined? Should we return one subfunction
-            # for each value component or only for those not mapped to another?
-            # I think split should ignore the symmetry.
+        if element.symmetry():
             error("Split not implemented for symmetric tensor elements.")
 
-    # Compute value size
-    value_size = product(element.value_shape())
-    actual_value_size = value_size
+    if len(v.ufl_shape) != 1:
+        error("Don't know how to split tensor valued mixed functions without flattened index space.")
 
-    # Extract sub coefficient
-    offset = 0
+    # Compute value size and set default range end
+    value_size = product(element.value_shape())
+    if end is None:
+        end = value_size
+    else:
+        # Recursively dive into mixedelement in to subelement
+        # corresponding to beginning of range
+        j = begin
+        while True:
+            sub_i, j = element.extract_subelement_component(j)
+            element = element.sub_elements()[sub_i]
+            # Then break when we find the subelement that covers the whole range
+            if product(element.value_shape()) == (end - begin):
+                break
+
+    # Build expressions representing the subfunction of v for each subelement
+    offset = begin
     sub_functions = []
     for i, e in enumerate(element.sub_elements()):
+        # Get shape, size, indices, and v components
+        # corresponding to subelement value
         shape = e.value_shape()
+        strides = shape_to_strides(shape)
         rank = len(shape)
+        sub_size = product(shape)
+        subindices = [flatten_multiindex(c, strides)
+                      for c in compute_indices(shape)]
+        components = [v[k + offset] for k in subindices]
 
+        # Shape components into same shape as subelement
         if rank == 0:
-            # This subelement is a scalar, always maps to a single value
-            subv = v[offset]
-            offset += 1
-
-        elif rank == 1:
-            # This subelement is a vector, always maps to a sequence of values
-            sub_size, = shape
-            components = [v[j] for j in range(offset, offset + sub_size)]
+            subv, = components
+        elif rank <= 1:
             subv = as_vector(components)
-            offset += sub_size
-
         elif rank == 2:
-            # This subelement is a tensor, possibly with symmetries, slightly more complicated...
-
-            # Size of this subvalue
-            sub_size = product(shape)
-
-            # If this subelement is a symmetric element, subtract symmetric components
-            s = None
-            if isinstance(e, TensorElement):
-                s = e.symmetry()
-            s = s or EmptyDict
-            # If we do this, we must fix the size computation in MixedElement.__init__ as well
-            #actual_value_size -= len(s)
-            #sub_size -= len(s)
-            #print s
-            # Build list of lists of value components
-            components = []
-            for ii in range(shape[0]):
-                row = []
-                for jj in range(shape[1]):
-                    # Map component (i,j) through symmetry mapping
-                    c = (ii, jj)
-                    c = s.get(c, c)
-                    i, j = c
-                    # Extract component c of this subvalue from global tensor v
-                    if len(v.ufl_shape) == 1:
-                        # Mapping into a flattened vector
-                        k = offset + i*shape[1] + j
-                        component = v[k]
-                        #print "k, offset, i, j, shape, component", k, offset, i, j, shape, component
-                    elif len(v.ufl_shape) == 2:
-                        # Mapping into a concatenated tensor (is this a figment of my imagination?)
-                        error("Not implemented.")
-                        row_offset, col_offset = 0, 0 # TODO
-                        k = (row_offset + i, col_offset + j)
-                        component = v[k]
-                    row.append(component)
-                components.append(row)
-
-            # Make a matrix of the components
-            subv = as_matrix(components)
-            offset += sub_size
-
+            subv = as_matrix([components[i*shape[1]: (i+1)*shape[1]]
+                              for i in range(shape[0])])
         else:
-            # TODO: Handle rank > 2? Or is there such a thing?
-            error("Don't know how to split functions with sub functions of rank %d (yet)." % rank)
-            #for indices in compute_indices(shape):
-            #    #k = offset + sum(i*s for (i,s) in izip(indices, shape[1:] + (1,)))
-            #    vs.append(v[indices])
+            error("Don't know how to split functions with sub functions of rank %d." % rank)
 
+        offset += sub_size
         sub_functions.append(subv)
 
-    ufl_assert(actual_value_size == offset, "Logic breach in function splitting.")
+    if end != offset:
+        error("Function splitting failed to extract components for whole intended range. Something is wrong.")
 
     return tuple(sub_functions)
diff --git a/ufl/tensoralgebra.py b/ufl/tensoralgebra.py
index 05a93e2..c5f7946 100644
--- a/ufl/tensoralgebra.py
+++ b/ufl/tensoralgebra.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Compound tensor algebra operations."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,17 +18,17 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
-from ufl.log import warning
-from ufl.assertions import ufl_assert
+from ufl.log import error
+from ufl.utils.py23 import as_native_strings
+from ufl.core.expr import ufl_err_str
+from ufl.core.ufl_type import ufl_type
 from ufl.constantvalue import Zero
 from ufl.algebra import Operator
 from ufl.precedence import parstr
 from ufl.sorting import sorted_expr
-from ufl.core.ufl_type import ufl_type
 from ufl.index_combination_utils import merge_nonoverlapping_indices
 
-
-### Algebraic operations on tensors:
+# Algebraic operations on tensors:
 # FloatValues:
 #   dot(a,b)      = a*b
 #   inner(a,b)    = a*b
@@ -53,11 +53,13 @@ from ufl.index_combination_utils import merge_nonoverlapping_indices
 #   dot(x,y):   last index of x has same dimension as first index of y
 #   inner(x,y): shape of x equals the shape of y
 
+
 # --- Classes representing compound tensor algebra operations ---
 
 @ufl_type(is_abstract=True)
 class CompoundTensorOperator(Operator):
     __slots__ = ()
+
     def __init__(self, operands):
         Operator.__init__(self, operands)
 
@@ -65,33 +67,34 @@ class CompoundTensorOperator(Operator):
 #       This would simplify some algorithms. The only
 #       problem is we can't use + in many algorithms because
 #       this type should be expanded by expand_compounds.
-#class TensorSum(CompoundTensorOperator):
-#    "Sum of nonscalar expressions."
-#    pass
+# class TensorSum(CompoundTensorOperator):
+#     "Sum of nonscalar expressions."
+#     pass
 
 # TODO: Use this similarly to TensorSum?
 #       This would simplify some algorithms. The only
 #       problem is we can't use / in many algorithms because
 #       this type should be expanded by expand_compounds.
-#class TensorDivision(CompoundTensorOperator):
-#    "Division of nonscalar expression with a scalar expression."
-#    pass
+# class TensorDivision(CompoundTensorOperator):
+#     "Division of nonscalar expression with a scalar expression."
+#     pass
 
 # TODO: Use this similarly to TensorSum?
 #       This would simplify some algorithms. The only
 #       problem is we can't use * in many algorithms because
 #       this type should be expanded by expand_compounds.
-#class MatrixProduct(CompoundTensorOperator):
-#    "Product of a matrix with a matrix or vector."
-#    pass
+# class MatrixProduct(CompoundTensorOperator):
+#     "Product of a matrix with a matrix or vector."
+#     pass
 
 # TODO: Use this similarly to TensorSum?
 #       This would simplify some algorithms. The only
 #       problem is we can't use abs in many algorithms because
 #       this type should be expanded by expand_compounds.
-#class TensorAbs(CompoundTensorOperator):
-#    "Absolute value of nonscalar expression."
-#    pass
+# class TensorAbs(CompoundTensorOperator):
+#     "Absolute value of nonscalar expression."
+#     pass
+
 
 @ufl_type(is_shaping=True, num_ops=1, inherit_indices_from_operand=0)
 class Transposed(CompoundTensorOperator):
@@ -105,7 +108,8 @@ class Transposed(CompoundTensorOperator):
 
     def __init__(self, A):
         CompoundTensorOperator.__init__(self, (A,))
-        ufl_assert(len(A.ufl_shape) == 2, "Transposed is only defined for rank 2 tensors.")
+        if len(A.ufl_shape) != 2:
+            error("Transposed is only defined for rank 2 tensors.")
 
     @property
     def ufl_shape(self):
@@ -115,12 +119,13 @@ class Transposed(CompoundTensorOperator):
     def __str__(self):
         return "%s^T" % parstr(self.ufl_operands[0], self)
 
-    def __repr__(self):
-        return "Transposed(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=2)
 class Outer(CompoundTensorOperator):
-    __slots__ = ("ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings((
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+        ))
 
     def __new__(cls, a, b):
         ash, bsh = a.ufl_shape, b.ufl_shape
@@ -142,19 +147,22 @@ class Outer(CompoundTensorOperator):
         return self.ufl_operands[0].ufl_shape + self.ufl_operands[1].ufl_shape
 
     def __str__(self):
-        return "%s (X) %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
+        return "%s (X) %s" % (parstr(self.ufl_operands[0], self),
+                              parstr(self.ufl_operands[1], self))
 
-    def __repr__(self):
-        return "Outer(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
 @ufl_type(num_ops=2)
 class Inner(CompoundTensorOperator):
-    __slots__ = ("ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings((
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+        ))
 
     def __new__(cls, a, b):
         # Checks
         ash, bsh = a.ufl_shape, b.ufl_shape
-        ufl_assert(ash == bsh, "Shape mismatch.")
+        if ash != bsh:
+            error("Shapes do not match: %s and %s." % (ufl_err_str(a), ufl_err_str(b)))
 
         # Simplification
         if isinstance(a, Zero) or isinstance(b, Zero):
@@ -180,14 +188,16 @@ class Inner(CompoundTensorOperator):
     ufl_shape = ()
 
     def __str__(self):
-        return "%s : %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
+        return "%s : %s" % (parstr(self.ufl_operands[0], self),
+                            parstr(self.ufl_operands[1], self))
 
-    def __repr__(self):
-        return "Inner(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
 @ufl_type(num_ops=2)
 class Dot(CompoundTensorOperator):
-    __slots__ = ("ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings((
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+        ))
 
     def __new__(cls, a, b):
         ash = a.ufl_shape
@@ -196,18 +206,18 @@ class Dot(CompoundTensorOperator):
         scalar = (ar == 0 and br == 0)
 
         # Checks
-        ufl_assert((ar >= 1 and br >= 1) or scalar,
-            "Dot product requires non-scalar arguments, "
-            "got arguments with ranks %d and %d." %
-            (ar, br))
-        ufl_assert(scalar or ash[-1] == bsh[0], "Dimension mismatch in dot product.")
+        if not ((ar >= 1 and br >= 1) or scalar):
+            error("Dot product requires non-scalar arguments, "
+                  "got arguments with ranks %d and %d." % (ar, br))
+        if not (scalar or ash[-1] == bsh[0]):
+            error("Dimension mismatch in dot product.")
 
         # Simplification
         if isinstance(a, Zero) or isinstance(b, Zero):
             shape = ash[:-1] + bsh[1:]
             fi, fid = merge_nonoverlapping_indices(a, b)
             return Zero(shape, fi, fid)
-        elif scalar: # TODO: Move this to def dot()?
+        elif scalar:  # TODO: Move this to def dot()?
             return a * b
 
         return CompoundTensorOperator.__new__(cls)
@@ -223,22 +233,25 @@ class Dot(CompoundTensorOperator):
         return self.ufl_operands[0].ufl_shape[:-1] + self.ufl_operands[1].ufl_shape[1:]
 
     def __str__(self):
-        return "%s . %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
+        return "%s . %s" % (parstr(self.ufl_operands[0], self),
+                            parstr(self.ufl_operands[1], self))
 
-    def __repr__(self):
-        return "Dot(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
 @ufl_type(num_ops=2)
 class Cross(CompoundTensorOperator):
-    __slots__ = ("ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings((
+        "ufl_free_indices",
+        "ufl_index_dimensions",
+        ))
 
     def __new__(cls, a, b):
         ash = a.ufl_shape
         bsh = b.ufl_shape
 
         # Checks
-        ufl_assert(len(ash) == 1 and ash == bsh,
-            "Cross product requires arguments of rank 1.")
+        if not (len(ash) == 1 and ash == bsh):
+            error("Cross product requires arguments of rank 1, got %s and %s." % (
+                ufl_err_str(a), ufl_err_str(b)))
 
         # Simplification
         if isinstance(a, Zero) or isinstance(b, Zero):
@@ -256,10 +269,9 @@ class Cross(CompoundTensorOperator):
     ufl_shape = (3,)
 
     def __str__(self):
-        return "%s x %s" % (parstr(self.ufl_operands[0], self), parstr(self.ufl_operands[1], self))
+        return "%s x %s" % (parstr(self.ufl_operands[0], self),
+                            parstr(self.ufl_operands[1], self))
 
-    def __repr__(self):
-        return "Cross(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
 @ufl_type(num_ops=1, inherit_indices_from_operand=0)
 class Trace(CompoundTensorOperator):
@@ -267,7 +279,8 @@ class Trace(CompoundTensorOperator):
 
     def __new__(cls, A):
         # Checks
-        ufl_assert(len(A.ufl_shape) == 2, "Trace of tensor with rank != 2 is undefined.")
+        if len(A.ufl_shape) != 2:
+            error("Trace of tensor with rank != 2 is undefined.")
 
         # Simplification
         if isinstance(A, Zero):
@@ -283,8 +296,6 @@ class Trace(CompoundTensorOperator):
     def __str__(self):
         return "tr(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Trace(%r)" % self.ufl_operands[0]
 
 @ufl_type(is_scalar=True, num_ops=1)
 class Determinant(CompoundTensorOperator):
@@ -296,12 +307,12 @@ class Determinant(CompoundTensorOperator):
         Afi = A.ufl_free_indices
 
         # Checks
-        ufl_assert(r == 0 or r == 2,
-            "Determinant of tensor with rank != 2 is undefined.")
-        ufl_assert(r == 0 or sh[0] == sh[1],
-            "Cannot take determinant of rectangular rank 2 tensor.")
-        ufl_assert(not Afi,
-            "Not expecting free indices in determinant.")
+        if r not in (0, 2):
+            error("Determinant of tensor with rank != 2 is undefined.")
+        if r == 2 and sh[0] != sh[1]:
+            error("Cannot take determinant of rectangular rank 2 tensor.")
+        if Afi:
+            error("Not expecting free indices in determinant.")
 
         # Simplification
         if isinstance(A, Zero):
@@ -317,10 +328,9 @@ class Determinant(CompoundTensorOperator):
     def __str__(self):
         return "det(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Determinant(%r)" % self.ufl_operands[0]
 
-# TODO: Drop Inverse and represent it as product of Determinant and Cofactor?
+# TODO: Drop Inverse and represent it as product of Determinant and
+# Cofactor?
 @ufl_type(is_index_free=True, num_ops=1)
 class Inverse(CompoundTensorOperator):
     __slots__ = ()
@@ -343,7 +353,7 @@ class Inverse(CompoundTensorOperator):
         if r != 2:
             error("Inverse of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            error("Cannot take inverse of rectangular matrix with dimensions %s." % repr(sh))
+            error("Cannot take inverse of rectangular matrix with dimensions %s." % (sh,))
 
         return CompoundTensorOperator.__new__(cls)
 
@@ -357,8 +367,6 @@ class Inverse(CompoundTensorOperator):
     def __str__(self):
         return "%s^-1" % parstr(self.ufl_operands[0], self)
 
-    def __repr__(self):
-        return "Inverse(%r)" % self.ufl_operands[0]
 
 @ufl_type(is_index_free=True, num_ops=1)
 class Cofactor(CompoundTensorOperator):
@@ -369,11 +377,14 @@ class Cofactor(CompoundTensorOperator):
 
         # Checks
         sh = A.ufl_shape
-        ufl_assert(len(sh) == 2, "Cofactor of tensor with rank != 2 is undefined.")
+        if len(sh) != 2:
+            error("Cofactor of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            error("Cannot take cofactor of rectangular matrix with dimensions %s." % repr(sh))
-        ufl_assert(not A.ufl_free_indices, "Not expecting free indices in Cofactor.")
-        ufl_assert(not isinstance(A, Zero), "Cannot take cofactor of zero matrix.")
+            error("Cannot take cofactor of rectangular matrix with dimensions %s." % (sh,))
+        if A.ufl_free_indices:
+            error("Not expecting free indices in Cofactor.")
+        if isinstance(A, Zero):
+            error("Cannot take cofactor of zero matrix.")
 
     @property
     def ufl_shape(self):
@@ -382,8 +393,6 @@ class Cofactor(CompoundTensorOperator):
     def __str__(self):
         return "cofactor(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Cofactor(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class Deviatoric(CompoundTensorOperator):
@@ -393,10 +402,12 @@ class Deviatoric(CompoundTensorOperator):
         sh = A.ufl_shape
 
         # Checks
-        ufl_assert(len(sh) == 2, "Deviatoric part of tensor with rank != 2 is undefined.")
+        if len(sh) != 2:
+            error("Deviatoric part of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            error("Cannot take deviatoric part of rectangular matrix with dimensions %s." % repr(sh))
-        ufl_assert(not A.ufl_free_indices, "Not expecting free indices in Deviatoric.")
+            error("Cannot take deviatoric part of rectangular matrix with dimensions %s." % (sh,))
+        if A.ufl_free_indices:
+            error("Not expecting free indices in Deviatoric.")
 
         # Simplification
         if isinstance(A, Zero):
@@ -410,8 +421,6 @@ class Deviatoric(CompoundTensorOperator):
     def __str__(self):
         return "dev(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Deviatoric(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class Skew(CompoundTensorOperator):
@@ -422,10 +431,12 @@ class Skew(CompoundTensorOperator):
         Afi = A.ufl_free_indices
 
         # Checks
-        ufl_assert(len(sh) == 2, "Skew symmetric part of tensor with rank != 2 is undefined.")
+        if len(sh) != 2:
+            error("Skew symmetric part of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            error("Cannot take skew part of rectangular matrix with dimensions %s." % repr(sh))
-        ufl_assert(not Afi, "Not expecting free indices in Skew.")
+            error("Cannot take skew part of rectangular matrix with dimensions %s." % (sh,))
+        if Afi:
+            error("Not expecting free indices in Skew.")
 
         # Simplification
         if isinstance(A, Zero):
@@ -439,8 +450,6 @@ class Skew(CompoundTensorOperator):
     def __str__(self):
         return "skew(%s)" % self.ufl_operands[0]
 
-    def __repr__(self):
-        return "Skew(%r)" % self.ufl_operands[0]
 
 @ufl_type(num_ops=1, inherit_shape_from_operand=0, inherit_indices_from_operand=0)
 class Sym(CompoundTensorOperator):
@@ -451,10 +460,12 @@ class Sym(CompoundTensorOperator):
         Afi = A.ufl_free_indices
 
         # Checks
-        ufl_assert(len(sh) == 2, "Symmetric part of tensor with rank != 2 is undefined.")
+        if len(sh) != 2:
+            error("Symmetric part of tensor with rank != 2 is undefined.")
         if sh[0] != sh[1]:
-            error("Cannot take symmetric part of rectangular matrix with dimensions %s." % repr(sh))
-        ufl_assert(not Afi, "Not expecting free indices in Sym.")
+            error("Cannot take symmetric part of rectangular matrix with dimensions %s." % (sh,))
+        if Afi:
+            error("Not expecting free indices in Sym.")
 
         # Simplification
         if isinstance(A, Zero):
@@ -467,6 +478,3 @@ class Sym(CompoundTensorOperator):
 
     def __str__(self):
         return "sym(%s)" % self.ufl_operands[0]
-
-    def __repr__(self):
-        return "Sym(%r)" % self.ufl_operands[0]
diff --git a/ufl/tensors.py b/ufl/tensors.py
index d189af1..532d210 100644
--- a/ufl/tensors.py
+++ b/ufl/tensors.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 """Classes used to group scalar expressions into expressions with rank > 0."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -17,13 +17,14 @@
 #
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
+#
+# Modified by Massimiliano Leoni, 2016.
 
 from six.moves import zip
 from six.moves import xrange as range
 
-from ufl.log import warning, error
-from ufl.utils.dicts import subdict, EmptyDict
-from ufl.assertions import ufl_assert
+from ufl.utils.py23 import as_native_strings
+from ufl.log import error
 from ufl.core.ufl_type import ufl_type
 from ufl.core.expr import Expr
 from ufl.core.operator import Operator
@@ -32,6 +33,7 @@ from ufl.core.multiindex import Index, FixedIndex, MultiIndex, indices
 from ufl.indexed import Indexed
 from ufl.index_combination_utils import remove_indices
 
+
 # --- Classes representing tensors of UFL expressions ---
 
 @ufl_type(is_shaping=True, num_ops="varying", inherit_indices_from_operand=0)
@@ -40,15 +42,16 @@ class ListTensor(Operator):
     __slots__ = ()
 
     def __new__(cls, *expressions):
-        # All lists and tuples should already be unwrapped in as_tensor
+        # All lists and tuples should already be unwrapped in
+        # as_tensor
         if any(not isinstance(e, Expr) for e in expressions):
             error("Expecting only UFL expressions in ListTensor constructor.")
 
         # Get properties of the first expression
         e0 = expressions[0]
-        sh    = e0.ufl_shape
-        fi    = e0.ufl_free_indices
-        fid   = e0.ufl_index_dimensions
+        sh = e0.ufl_shape
+        fi = e0.ufl_free_indices
+        fid = e0.ufl_index_dimensions
 
         # Obviously, each subexpression must have the same shape
         if any(sh != e.ufl_shape for e in expressions[1:]):
@@ -70,17 +73,17 @@ class ListTensor(Operator):
 
         # Checks
         indexset = set(self.ufl_operands[0].ufl_free_indices)
-        ufl_assert(all(not (indexset ^ set(e.ufl_free_indices)) for e in self.ufl_operands),
-            "Can't combine subtensor expressions with different sets of free indices.")
+        if not all(not (indexset ^ set(e.ufl_free_indices)) for e in self.ufl_operands):
+            error("Can't combine subtensor expressions with different sets of free indices.")
 
     @property
     def ufl_shape(self):
         return (len(self.ufl_operands),) + self.ufl_operands[0].ufl_shape
 
     def evaluate(self, x, mapping, component, index_values, derivatives=()):
-        ufl_assert(len(component) == len(self.ufl_shape),
-                   "Can only evaluate scalars, expecting a component "
-                   "tuple of length %d, not %s." % (len(self.ufl_shape), component))
+        if len(component) != len(self.ufl_shape):
+            error("Can only evaluate scalars, expecting a component "
+                  "tuple of length %d, not %s." % (len(self.ufl_shape), component))
         a = self.ufl_operands[component[0]]
         component = component[1:]
         if derivatives:
@@ -119,13 +122,11 @@ class ListTensor(Operator):
                 return "%s[%s]" % (ind, s)
         return substring(self.ufl_operands, 0)
 
-    def __repr__(self):
-        return "ListTensor(%s)" % ", ".join(repr(e) for e in self.ufl_operands)
 
 @ufl_type(is_shaping=True, num_ops="varying")
 class ComponentTensor(Operator):
     """UFL operator type: Maps the free indices of a scalar valued expression to tensor axes."""
-    __slots__ = ("ufl_shape", "ufl_free_indices", "ufl_index_dimensions")
+    __slots__ = as_native_strings(("ufl_shape", "ufl_free_indices", "ufl_index_dimensions"))
 
     def __new__(cls, expression, indices):
 
@@ -140,17 +141,20 @@ class ComponentTensor(Operator):
         return Operator.__new__(cls)
 
     def __init__(self, expression, indices):
-        ufl_assert(isinstance(expression, Expr), "Expecting ufl expression.")
-        ufl_assert(expression.ufl_shape == (), "Expecting scalar valued expression.")
-        ufl_assert(isinstance(indices, MultiIndex), "Expecting a MultiIndex.")
-        ufl_assert(all(isinstance(i, Index) for i in indices),
-           "Expecting sequence of Index objects, not %s." % repr(indices))
+        if not isinstance(expression, Expr):
+            error("Expecting ufl expression.")
+        if expression.ufl_shape != ():
+            error("Expecting scalar valued expression.")
+        if not isinstance(indices, MultiIndex):
+            error("Expecting a MultiIndex.")
+        if not all(isinstance(i, Index) for i in indices):
+            error("Expecting sequence of Index objects, not %s." % indices._ufl_err_str_())
 
         Operator.__init__(self, (expression, indices))
 
         fi, fid, sh = remove_indices(expression.ufl_free_indices,
-                                 expression.ufl_index_dimensions,
-                                 [ind.count() for ind in indices])
+                                     expression.ufl_index_dimensions,
+                                     [ind.count() for ind in indices])
         self.ufl_free_indices = fi
         self.ufl_index_dimensions = fid
         self.ufl_shape = sh
@@ -160,7 +164,6 @@ class ComponentTensor(Operator):
         if isinstance(expressions, Indexed):
             A, ii = expressions.ufl_operands
             if indices == ii:
-                #print "RETURNING", A, "FROM", expressions, indices, "SELF IS", self
                 return A
         return Operator._ufl_expr_reconstruct_(self, expressions, indices)
 
@@ -171,8 +174,8 @@ class ComponentTensor(Operator):
         indices = self.ufl_operands[1]
         a = self.ufl_operands[0]
 
-        ufl_assert(len(indices) == len(component),
-                   "Expecting a component matching the indices tuple.")
+        if len(indices) != len(component):
+            error("Expecting a component matching the indices tuple.")
 
         # Map component to indices
         for i, c in zip(indices, component):
@@ -188,8 +191,6 @@ class ComponentTensor(Operator):
     def __str__(self):
         return "{ A | A_{%s} = %s }" % (self.ufl_operands[1], self.ufl_operands[0])
 
-    def __repr__(self):
-        return "ComponentTensor(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
 
 # --- User-level functions to wrap expressions in the correct way ---
 
@@ -199,6 +200,7 @@ def numpy2nestedlists(arr):
         return arr
     return [numpy2nestedlists(arr[k]) for k in range(arr.shape[0])]
 
+
 def _as_list_tensor(expressions):
     if isinstance(expressions, (list, tuple)):
         expressions = [_as_list_tensor(e) for e in expressions]
@@ -206,6 +208,7 @@ def _as_list_tensor(expressions):
     else:
         return as_ufl(expressions)
 
+
 def from_numpy_to_lists(expressions):
     try:
         import numpy
@@ -215,20 +218,21 @@ def from_numpy_to_lists(expressions):
         pass
     return expressions
 
+
 def as_tensor(expressions, indices=None):
     """UFL operator: Make a tensor valued expression.
 
     This works in two different ways, by using indices or lists.
 
-    1) Returns A such that A[indices] = expressions.
-    If indices are provided, expressions must be a scalar
+    1) Returns :math:`A` such that :math:`A` [*indices*] = *expressions*.
+    If *indices* are provided, *expressions* must be a scalar
     valued expression with all the provided indices among
     its free indices. This operator will then map each of these
     indices to a tensor axis, thereby making a tensor valued
     expression from a scalar valued expression with free indices.
 
-    2) Returns A such that A[k,...] = expressions[k].
-    If no indices are provided, expressions must be a list
+    2) Returns :math:`A` such that :math:`A[k,...]` = *expressions*[k].
+    If no indices are provided, *expressions* must be a list
     or tuple of expressions. The expressions can also consist
     of recursively nested lists to build higher rank tensors.
     """
@@ -245,7 +249,8 @@ def as_tensor(expressions, indices=None):
         if not isinstance(expressions, (list, tuple)):
             error("Expecting nested list or tuple.")
 
-        # Recursive conversion from nested lists to nested ListTensor objects
+        # Recursive conversion from nested lists to nested ListTensor
+        # objects
         return _as_list_tensor(expressions)
     else:
         # Make sure we have a tuple of indices
@@ -269,12 +274,14 @@ def as_tensor(expressions, indices=None):
         # Make a tensor from given scalar expression with free indices
         return ComponentTensor(expressions, indices)
 
-def as_matrix(expressions, indices = None):
-    "UFL operator: As as_tensor(), but limited to rank 2 tensors."
+
+def as_matrix(expressions, indices=None):
+    "UFL operator: As *as_tensor()*, but limited to rank 2 tensors."
     if indices is None:
         # Allow as_matrix(as_matrix(A)) in user code
         if isinstance(expressions, Expr):
-            ufl_assert(len(expressions.ufl_shape) == 2, "Expecting rank 2 tensor.")
+            if len(expressions.ufl_shape) != 2:
+                error("Expecting rank 2 tensor.")
             return expressions
 
         # To avoid importing numpy unneeded, it's quite slow...
@@ -282,21 +289,24 @@ def as_matrix(expressions, indices = None):
             expressions = from_numpy_to_lists(expressions)
 
         # Check for expected list structure
-        ufl_assert(isinstance(expressions, (list, tuple)),
-            "Expecting nested list or tuple of Exprs.")
-        ufl_assert(isinstance(expressions[0], (list, tuple)),
-            "Expecting nested list or tuple of Exprs.")
+        if not isinstance(expressions, (list, tuple)):
+            error("Expecting nested list or tuple of Exprs.")
+        if not isinstance(expressions[0], (list, tuple)):
+            error("Expecting nested list or tuple of Exprs.")
     else:
-        ufl_assert(len(indices) == 2, "Expecting exactly two indices.")
+        if len(indices) != 2:
+            error("Expecting exactly two indices.")
 
     return as_tensor(expressions, indices)
 
-def as_vector(expressions, index = None):
-    "UFL operator: As as_tensor(), but limited to rank 1 tensors."
+
+def as_vector(expressions, index=None):
+    "UFL operator: As ``as_tensor()``, but limited to rank 1 tensors."
     if index is None:
         # Allow as_vector(as_vector(v)) in user code
         if isinstance(expressions, Expr):
-            ufl_assert(len(expressions.ufl_shape) == 1, "Expecting rank 1 tensor.")
+            if len(expressions.ufl_shape) != 1:
+                error("Expecting rank 1 tensor.")
             return expressions
 
         # To avoid importing numpy unneeded, it's quite slow...
@@ -304,14 +314,16 @@ def as_vector(expressions, index = None):
             expressions = from_numpy_to_lists(expressions)
 
         # Check for expected list structure
-        ufl_assert(isinstance(expressions, (list, tuple)),
-            "Expecting nested list or tuple of Exprs.")
+        if not isinstance(expressions, (list, tuple)):
+            error("Expecting nested list or tuple of Exprs.")
     else:
-        ufl_assert(isinstance(index, Index), "Expecting a single Index object.")
+        if not isinstance(index, Index):
+            error("Expecting a single Index object.")
         index = (index,)
 
     return as_tensor(expressions, index)
 
+
 def as_scalar(expression):
     """Given a scalar or tensor valued expression A, returns either of the tuples::
 
@@ -324,6 +336,7 @@ def as_scalar(expression):
         expression = expression[ii]
     return expression, ii
 
+
 def as_scalars(*expressions):
     """Given multiple scalar or tensor valued expressions A, returns either of the tuples::
 
@@ -336,52 +349,65 @@ def as_scalars(*expressions):
         expressions = [expression[ii] for expression in expressions]
     return expressions, ii
 
+
 def relabel(A, indexmap):
-    "UFL operator: Relabel free indices of A with new indices, using the given mapping."
+    "UFL operator: Relabel free indices of :math:`A` with new indices, using the given mapping."
     ii = tuple(sorted(indexmap.keys()))
     jj = tuple(indexmap[i] for i in ii)
-    ufl_assert(all(isinstance(i, Index) for i in ii), "Expecting Index objects.")
-    ufl_assert(all(isinstance(j, Index) for j in jj), "Expecting Index objects.")
+    if not all(isinstance(i, Index) for i in ii):
+        error("Expecting Index objects.")
+    if not all(isinstance(j, Index) for j in jj):
+        error("Expecting Index objects.")
     return as_tensor(A, ii)[jj]
 
+
 # --- Experimental support for dyadic notation:
 
 def unit_list(i, n):
     return [(1 if i == j else 0) for j in range(n)]
 
+
 def unit_list2(i, j, n):
     return [[(1 if (i == i0 and j == j0) else 0) for j0 in range(n)] for i0 in range(n)]
 
+
 def unit_vector(i, d):
-    "UFL value: A constant unit vector in direction i with dimension d."
+    "UFL value: A constant unit vector in direction *i* with dimension *d*."
     return as_vector(unit_list(i, d))
 
+
 def unit_vectors(d):
-    "UFL value: A tuple of constant unit vectors in all directions with dimension d."
+    """UFL value: A tuple of constant unit vectors in all directions with
+    dimension *d*."""
     return tuple(unit_vector(i, d) for i in range(d))
 
+
 def unit_matrix(i, j, d):
-    "UFL value: A constant unit matrix in direction i,j with dimension d."
+    "UFL value: A constant unit matrix in direction *i*,*j* with dimension *d*."
     return as_matrix(unit_list2(i, j, d))
 
+
 def unit_matrices(d):
-    "UFL value: A tuple of constant unit matrices in all directions with dimension d."
+    """UFL value: A tuple of constant unit matrices in all directions with
+    dimension *d*."""
     return tuple(unit_matrix(i, j, d) for i in range(d) for j in range(d))
 
+
 def dyad(d, *iota):
     "TODO: Develop this concept, can e.g. write A[i,j]*dyad(j,i) for the transpose."
     from ufl.constantvalue import Identity
-    from ufl.operators import outer # a bit of circular dependency issue here
+    from ufl.operators import outer  # a bit of circular dependency issue here
     I = Identity(d)
     i = iota[0]
-    e = as_vector(I[i,:], i)
+    e = as_vector(I[i, :], i)
     for i in iota[1:]:
-        e = outer(e, as_vector(I[i,:], i))
+        e = outer(e, as_vector(I[i, :], i))
     return e
 
+
 def unit_indexed_tensor(shape, component):
     from ufl.constantvalue import Identity
-    from ufl.operators import outer # a bit of circular dependency issue here
+    from ufl.operators import outer  # a bit of circular dependency issue here
     r = len(shape)
     if r == 0:
         return 0, ()
@@ -398,6 +424,7 @@ def unit_indexed_tensor(shape, component):
         E = outer(E, e)
     return E, jj
 
+
 def unwrap_list_tensor(lt):
     components = []
     sh = lt.ufl_shape
diff --git a/ufl/utils/counted.py b/ufl/utils/counted.py
index 3f7b8c9..40c6e35 100644
--- a/ufl/utils/counted.py
+++ b/ufl/utils/counted.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Utilites for types with a global unique counter attached to each object."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,6 +19,9 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 
+from ufl.utils.py23 import as_native_strings
+
+
 def counted_init(self, count=None, countedclass=None):
     "Initialize a counted object, see ExampleCounted below for how to use."
 
@@ -40,7 +43,7 @@ class ExampleCounted(object):
     Mimic this class to create globally counted objects within a single type.
     """
     # Store the count for each object
-    __slots__ = ("_count",)
+    __slots__ = as_native_strings(("_count",))
 
     # Store a global counter with the class
     _globalcount = 0
diff --git a/ufl/utils/derivativetuples.py b/ufl/utils/derivativetuples.py
index 8a3d4f9..e7b21dc 100644
--- a/ufl/utils/derivativetuples.py
+++ b/ufl/utils/derivativetuples.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module contains a collection of utilities for representing partial derivatives as integer tuples."
 
-# Copyright (C) 2013-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2013-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -20,6 +20,7 @@
 
 import itertools
 
+
 def derivative_counts_to_listing(derivative_counts):
     """Convert a derivative count tuple to a derivative listing tuple.
 
@@ -27,11 +28,12 @@ def derivative_counts_to_listing(derivative_counts):
     in counting form as (0, 2, 1) meaning (dx^0, dy^2, dz^1)
     and in listing form as (1, 1, 2) meaning (dy, dy, dz).
     """
-    derivatives = [] # = 1
+    derivatives = []  # = 1
     for i, d in enumerate(derivative_counts):
-        derivatives.extend((i,)*d) # *= d/dx_i^d
+        derivatives.extend((i,)*d)  # *= d/dx_i^d
     return tuple(derivatives)
 
+
 def derivative_listing_to_counts(derivatives, gdim):
     """Convert a derivative listing tuple to a derivative count tuple.
 
@@ -44,6 +46,7 @@ def derivative_listing_to_counts(derivatives, gdim):
         derivative_counts[d] += 1
     return tuple(derivative_counts)
 
+
 def compute_derivative_tuples(n, gdim):
     """Compute the list of all derivative tuples for derivatives of
     given total order n and given geometric dimension gdim. This
diff --git a/ufl/utils/dicts.py b/ufl/utils/dicts.py
index 5c07105..473c888 100644
--- a/ufl/utils/dicts.py
+++ b/ufl/utils/dicts.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Various dict manipulation utilities."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,6 +21,7 @@
 from six import iterkeys, iteritems
 from six import advance_iterator as next
 
+
 def split_dict(d, criteria):
     "Split a dict d into two dicts based on a criteria on the keys."
     a = {}
@@ -32,27 +33,33 @@ def split_dict(d, criteria):
             b[k] = v
     return a, b
 
+
 def slice_dict(dictionary, keys, default=None):
     return tuple(dictionary.get(k, default) for k in keys)
 
+
 def some_key(a_dict):
     "Return an arbitrary key from a dictionary."
     return next(iterkeys(a_dict))
 
+
 def mergedicts(dicts):
     d = dict(dicts[0])
     for d2 in dicts[1:]:
         d.update(d2)
     return d
 
+
 def mergedicts2(d1, d2):
     d = dict(d1)
     d.update(d2)
     return d
 
+
 def subdict(superdict, keys):
     return dict((k, superdict[k]) for k in keys)
 
+
 def dict_sum(items):
     "Construct a dict, in between dict(items) and sum(items), by accumulating items for each key."
     d = {}
@@ -63,11 +70,15 @@ def dict_sum(items):
             d[k] += v
     return d
 
+
 class EmptyDictType(dict):
     def __setitem__(self, key, value):
         from ufl.log import error
         error("This is a frozen unique empty dictionary object, inserting values is an error.")
+
     def update(self, *args, **kwargs):
         from ufl.log import error
         error("This is a frozen unique empty dictionary object, inserting values is an error.")
+
+
 EmptyDict = EmptyDictType()
diff --git a/ufl/utils/formatting.py b/ufl/utils/formatting.py
index 9812731..c40bf5b 100644
--- a/ufl/utils/formatting.py
+++ b/ufl/utils/formatting.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Various string formatting utilities."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
+# Copyright (C) 2008-2016 Martin Sandve Alnæs and Anders Logg
 #
 # This file is part of UFL.
 #
@@ -18,6 +18,9 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+from six import string_types
+
+
 def camel2underscore(name):
     "Convert a CamelCaps string to underscore_syntax."
     letters = []
@@ -33,6 +36,7 @@ def camel2underscore(name):
         letters.append(l)
     return "".join(letters)
 
+
 def lstr(l):
     "Pretty-print list or tuple, invoking str() on items instead of repr() like str() does."
     if isinstance(l, list):
@@ -41,11 +45,13 @@ def lstr(l):
         return "(" + ", ".join(lstr(item) for item in l) + ")"
     return str(l)
 
+
 def dstr(d, colsize=80):
     "Pretty-print dictionary of key-value pairs."
     sorted_keys = sorted(d.keys())
     return tstr([(key, d[key]) for key in sorted_keys], colsize)
 
+
 def tstr(t, colsize=80):
     "Pretty-print list of tuples of key-value pairs."
     if not t:
@@ -62,7 +68,7 @@ def tstr(t, colsize=80):
     s = ""
     for (key, value) in t:
         key = str(key)
-        if isinstance(value, str):
+        if isinstance(value, string_types):
             value = "'%s'" % value
         else:
             value = str(value)
@@ -75,10 +81,12 @@ def tstr(t, colsize=80):
             space = " "*(keylen + 2)
     return s
 
+
 def sstr(s):
     "Pretty-print set."
     return ", ".join(str(x) for x in s)
 
+
 def istr(o):
     "Format object as string, inserting ? for None."
     if o is None:
@@ -86,6 +94,7 @@ def istr(o):
     else:
         return str(o)
 
+
 def estr(elements):
     "Format list of elements for printing."
     return ", ".join(e.shortstr() for e in elements)
diff --git a/ufl/utils/indexflattening.py b/ufl/utils/indexflattening.py
index 728aea1..5d22516 100644
--- a/ufl/utils/indexflattening.py
+++ b/ufl/utils/indexflattening.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "This module contains a collection of utilities for mapping between multiindices and a flattened index space."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -21,6 +21,7 @@
 from six.moves import zip
 from six.moves import xrange as range
 
+
 def shape_to_strides(sh):
     "Return a tuple of strides given a shape tuple."
     n = len(sh)
@@ -32,6 +33,7 @@ def shape_to_strides(sh):
         strides[i-1] = strides[i]*sh[i]
     return tuple(strides)
 
+
 def flatten_multiindex(ii, strides):
     "Return the flat index corresponding to the given multiindex."
     i = 0
@@ -39,6 +41,7 @@ def flatten_multiindex(ii, strides):
         i += c * s
     return i
 
+
 def unflatten_index(i, strides):
     "Return the multiindex corresponding to the given flat index."
     ii = []
diff --git a/ufl/utils/py23.py b/ufl/utils/py23.py
new file mode 100644
index 0000000..d2b9500
--- /dev/null
+++ b/ufl/utils/py23.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2016-2016 Martin Sandve Alnæs
+#
+# This file is part of UFL.
+#
+# UFL is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# UFL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with UFL. If not, see <http://www.gnu.org/licenses/>.
+
+"""Python 2/3 compatibility utilities."""
+
+import six
+
+
+if not six.PY2:
+    unicode = str
+
+    def as_native_str(s):
+        "Return s as unicode string, decoded using utf-8 if necessary."
+        if isinstance(s, bytes):
+            return s.decode("utf-8")
+        else:
+            return s
+else:
+    def as_native_str(s):
+        "Return s as bytes string, encoded using utf-8 if necessary."
+        if isinstance(s, unicode):
+            return s.encode("utf-8")
+        else:
+            return s
+
+
+def as_native_strings(stringlist):
+    return [as_native_str(s) for s in stringlist]
+
+
+def as_bytes(s):
+    "Return s if bytes, or encode unicode string to bytes using utf-8."
+    if isinstance(s, unicode):
+        return s.encode("utf-8")
+    else:
+        return s
+
+
+def as_unicode(s):
+    "Return s if unicode string, or decode bytes to unicode string using utf-8."
+    if isinstance(s, bytes):
+        return s.decode("utf-8")
+    else:
+        return s
diff --git a/ufl/utils/sequences.py b/ufl/utils/sequences.py
index 707b533..20ee3e1 100644
--- a/ufl/utils/sequences.py
+++ b/ufl/utils/sequences.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Various sequence manipulation utilities."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -19,8 +19,8 @@
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 from six.moves import zip
-import operator
-import time
+from six import string_types
+
 
 def product(sequence):
     "Return the product of all elements in a sequence."
@@ -29,21 +29,26 @@ def product(sequence):
         p *= f
     return p
 
+
 def unzip(seq):
     "Inverse operation of zip: unzip(zip(a, b)) == (a, b)"
     return [s[0] for s in seq], [s[1] for s in seq]
 
+
 def xor(a, b):
     return bool(a) if b else not a
 
+
 def or_tuples(seqa, seqb):
     "Return 'or' of all pairs in two sequences of same length."
     return tuple(a or b for (a, b) in zip(seqa, seqb))
 
+
 def and_tuples(seqa, seqb):
     "Return 'and' of all pairs in two sequences of same length."
     return tuple(a and b for (a, b) in zip(seqa, seqb))
 
+
 def iter_tree(tree):
     """Iterate over all nodes in a tree represented
     by lists of lists of leaves."""
@@ -54,9 +59,10 @@ def iter_tree(tree):
     else:
         yield tree
 
+
 def recursive_chain(lists):
     for l in lists:
-        if isinstance(l, str):
+        if isinstance(l, string_types):
             yield l
         else:
             for s in recursive_chain(l):
diff --git a/ufl/utils/sorting.py b/ufl/utils/sorting.py
index f7b9a46..044ab93 100644
--- a/ufl/utils/sorting.py
+++ b/ufl/utils/sorting.py
@@ -20,6 +20,8 @@
 
 from ufl.log import warning
 from six import itervalues, iteritems
+from six import string_types
+
 
 def topological_sorting(nodes, edges):
     """
@@ -69,7 +71,8 @@ def sorted_by_ufl_id(seq):
 
 def sorted_by_key(mapping):
     "Sort dict items by key, allowing different key types."
-    # Python3 doesn't allow comparing builtins of different type, therefore the typename trick here
+    # Python3 doesn't allow comparing builtins of different type,
+    # therefore the typename trick here
     def _key(x):
         return (type(x[0]).__name__, x[0])
     return sorted(iteritems(mapping), key=_key)
@@ -77,7 +80,8 @@ def sorted_by_key(mapping):
 
 def sorted_by_tuple_key(mapping):
     "Sort dict items by tuple valued keys, allowing different types as items of the key tuples."
-    # Python3 doesn't allow comparing builtins of different type, therefore the typename trick here
+    # Python3 doesn't allow comparing builtins of different type,
+    # therefore the typename trick here
     def _tuple_key(x):
         return tuple((type(k).__name__, k) for k in x[0])
     return sorted(iteritems(mapping), key=_tuple_key)
@@ -97,7 +101,7 @@ def canonicalize_metadata(metadata):
 
     if isinstance(metadata, dict):
         keys = sorted(metadata.keys())
-        assert all(isinstance(key, str) for key in keys)
+        assert all(isinstance(key, string_types) for key in keys)
         values = [metadata[key] for key in keys]
     elif isinstance(metadata, (tuple, list)):
         values = metadata
@@ -106,7 +110,7 @@ def canonicalize_metadata(metadata):
     for value in values:
         if isinstance(value, (dict, list, tuple)):
             value = canonicalize_metadata(value)
-        elif isinstance(value, (int, float, str)):
+        elif isinstance(value, (int, float, string_types)):
             value = str(value)
         else:
             warning("Applying str() to a metadata value of type {0}, don't know if this is safe.".format(type(value).__name__))
diff --git a/ufl/utils/stacks.py b/ufl/utils/stacks.py
index b677712..9cbf9c7 100644
--- a/ufl/utils/stacks.py
+++ b/ufl/utils/stacks.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Various utility data structures."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,6 +18,7 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+
 class Stack(list):
     "A stack datastructure."
     def __init__(self, *args):
@@ -29,6 +30,7 @@ class Stack(list):
     def peek(self):
         return self[-1]
 
+
 class StackDict(dict):
     "A dict that can be changed incrementally with 'd.push(k,v)' and have changes rolled back with 'k,v = d.pop()'."
     def __init__(self, *args, **kwargs):
diff --git a/ufl/utils/system.py b/ufl/utils/system.py
deleted file mode 100644
index 0ead587..0000000
--- a/ufl/utils/system.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# -*- coding: utf-8 -*-
-"Various utilities accessing system io."
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Johannes Ring
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
-# Taken from http://ivory.idyll.org/blog/mar-07/replacing-commands-with-subprocess
-from subprocess import Popen, PIPE, STDOUT
-from functools import reduce
-def get_status_output(cmd, input=None, cwd=None, env=None):
-    pipe = Popen(cmd, shell=True, cwd=cwd, env=env, stdout=PIPE, stderr=STDOUT)
-
-    (output, errout) = pipe.communicate(input=input)
-    assert not errout
-
-    status = pipe.returncode
-
-    return (status, output)
-
-def write_file(filename, text):
-    with open(filename, "w") as f:
-        f.write(text)
-
-def pdflatex(latexfilename, pdffilename, flags=""): # TODO: Options for this.
-    "Execute pdflatex to compile a latex file into pdf."
-    flags += "-file-line-error-style -interaction=nonstopmode"
-    latexcmd = "pdflatex"
-    cmd = "%s %s %s %s" % (latexcmd, flags, latexfilename, pdffilename)
-    s, o = get_status_output(cmd)
-    return s, o
-
-def openpdf(pdffilename):
-    "Open PDF file in external pdf viewer."
-    reader_cmd = "evince %s &" # TODO: Add option for which reader to use. Is there a portable way to do this? Like "get default pdf reader from os"?
-    cmd = reader_cmd % pdffilename
-    s, o = get_status_output(cmd)
-    return s, o
diff --git a/ufl/utils/timer.py b/ufl/utils/timer.py
deleted file mode 100644
index e454074..0000000
--- a/ufl/utils/timer.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-"Timer utilites."
-
-# Copyright (C) 2008-2015 Martin Sandve Alnæs and Anders Logg
-#
-# This file is part of UFL.
-#
-# UFL is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# UFL is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with UFL. If not, see <http://www.gnu.org/licenses/>.
-
-from six.moves import xrange as range
-import time
-
-class Timer(object):
-    def __init__(self, name):
-        self.name = name
-        self.times = []
-        self('begin %s' % self.name)
-
-    def __call__(self, msg):
-        self.times.append((time.time(), msg))
-
-    def end(self):
-        self('end %s' % self.name)
-
-    def __str__(self):
-        line = "-"*60
-        s = [line, "Timing of %s" % self.name]
-        for i in range(len(self.times)-1):
-            t = self.times[i+1][0] - self.times[i][0]
-            msg = self.times[i][1]
-            s.append("%9.2e s    %s" % (t, msg))
-        s.append('Total time: %9.2e s' % (self.times[-1][0] - self.times[0][0]))
-        s.append(line)
-        return '\n'.join(s)
diff --git a/ufl/utils/ufltypedicts.py b/ufl/utils/ufltypedicts.py
index 2bbf2b3..4aff13a 100644
--- a/ufl/utils/ufltypedicts.py
+++ b/ufl/utils/ufltypedicts.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 "Various utility data structures."
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -18,6 +18,7 @@
 # You should have received a copy of the GNU Lesser General Public License
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
+
 class UFLTypeDict(dict):
     def __init__(self):
         dict.__init__(self)
@@ -34,9 +35,11 @@ class UFLTypeDict(dict):
     def __contains__(self, key):
         return dict.__contains__(self, key._ufl_class_)
 
+
 class UFLTypeDefaultDict(dict):
     def __init__(self, default):
         dict.__init__(self)
+
         def make_default():
             return default
         self.setdefault(make_default)
diff --git a/ufl/variable.py b/ufl/variable.py
index f390525..aba43dd 100644
--- a/ufl/variable.py
+++ b/ufl/variable.py
@@ -2,7 +2,7 @@
 """Defines the Variable and Label classes, used to label
 expressions as variables for differentiation."""
 
-# Copyright (C) 2008-2015 Martin Sandve Alnæs
+# Copyright (C) 2008-2016 Martin Sandve Alnæs
 #
 # This file is part of UFL.
 #
@@ -20,8 +20,9 @@ expressions as variables for differentiation."""
 # along with UFL. If not, see <http://www.gnu.org/licenses/>.
 
 from ufl.utils.counted import counted_init
+from ufl.utils.py23 import as_native_str
+from ufl.utils.py23 import as_native_strings
 from ufl.log import error
-from ufl.assertions import ufl_assert
 from ufl.core.expr import Expr
 from ufl.core.ufl_type import ufl_type
 from ufl.core.terminal import Terminal
@@ -31,7 +32,7 @@ from ufl.constantvalue import as_ufl
 
 @ufl_type()
 class Label(Terminal):
-    __slots__ = ("_count",)
+    __slots__ = as_native_strings(("_count",))
 
     _globalcount = 0
 
@@ -46,7 +47,8 @@ class Label(Terminal):
         return "Label(%d)" % self._count
 
     def __repr__(self):
-        return "Label(%d)" % self._count
+        r = "Label(%d)" % self._count
+        return as_native_str(r)
 
     @property
     def ufl_shape(self):
@@ -90,9 +92,12 @@ class Variable(Operator):
             label = Label()
 
         # Checks
-        ufl_assert(isinstance(expression, Expr), "Expecting Expr.")
-        ufl_assert(isinstance(label, Label), "Expecting a Label.")
-        ufl_assert(not expression.ufl_free_indices, "Variable cannot wrap an expression with free indices.")
+        if not isinstance(expression, Expr):
+            error("Expecting Expr.")
+        if not isinstance(label, Label):
+            error("Expecting a Label.")
+        if expression.ufl_free_indices:
+            error("Variable cannot wrap an expression with free indices.")
 
         Operator.__init__(self, (expression, label))
 
@@ -110,12 +115,10 @@ class Variable(Operator):
         return self.ufl_operands[1]
 
     def __eq__(self, other):
-        return (isinstance(other, Variable)
-                and self.ufl_operands[1] == other.ufl_operands[1]
-                and self.ufl_operands[0] == other.ufl_operands[0])
+        return (isinstance(other, Variable) and
+                self.ufl_operands[1] == other.ufl_operands[1] and
+                self.ufl_operands[0] == other.ufl_operands[0])
 
     def __str__(self):
-        return "var%d(%s)" % (self.ufl_operands[1].count(), self.ufl_operands[0])
-
-    def __repr__(self):
-        return "Variable(%r, %r)" % (self.ufl_operands[0], self.ufl_operands[1])
+        return "var%d(%s)" % (self.ufl_operands[1].count(),
+                              self.ufl_operands[0])

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/fenics/ufl.git



More information about the debian-science-commits mailing list