Roadmap for the development of UFL
----------------------------------

Make diff(u, cell.n) -> dot(cell.n, grad(u))
and Dn(u) -> diff(u, u.cell().n) -> dot(cell.n, grad(u))

# Tests:
    - Write more tests!
    - In particular write tests for the core algorithms, ideally covering all operators.

# Documentation:
    - Add grouped lists of operators to ufl module docstring!
    - Rewrite/improve all error messages (collect strings in separate file?)
    - Improve operator docstrings (use epydoc @param and @return for the more complicated functions)
    - Improve manual.

# Prettyness and readability (medium priority, useful while debugging...):
    - Finish precedence list to improve parentesis use in __str__ and __repr__ and ufl2latex.
    - Rewrite ufl2latex as described in its comments (use pre- and post-handlers)
    - Improve dot-rendering with compact symbols for all node types
      (evt add option to switch between repr style and greek style)
    - Add dot-rendering to graph class: G = Graph(e); print G.dot_format()
    - Add utility "showdot(e)" for interactive experimentation. Need a good way to show images to do this.

# Class hierarchy changes:
    - Streamline design when we have good tests. Need a clear line between compounds and non-compounds.
    - Add TensorSum, TensorDivision, ProductOfTensors, compound types just like Grad, Div. (evt CompoundSum, CompoundDivision, CompoundProduct, perhaps there are others)

# Algorithms:
    - Attaching flags to expression nodes to make effective application of expansions more streamlined.
    - Improve algorithm for computing worst case quadrature degree with more rules
    - (hopefully not...) If AD needs to be applied in a compiler context, we need a 
      framework for representing unapplied form transformations.
    - Determine whether or not a bilinear form is self-adjoint (symmetric)

# Simplification:
    - Improved simplification of Indexed/ComponentTensor combinations.
    - Implement better simplification as an algorithm, or add 
      more simplification features to __new__ implementations?
      One important such basic simplification is to extract constant 
      factors from all operands in a sum, e.g. from:
              (-1 * (v_1)[0])
              +
              (
              (2 * (v_1)[0])
              +
              (-1 * (v_1)[0])
      to:
              (-1+2-1) * (v_1)[0]) = 0
      Once form compilers and regression tests are up and running,
      we can consider wether the backside of this (which is complicated)
      is important enough to avoid doing this by default...

# Optimization (low priority unless critical bottlenecks are found):
    - Optimize expand_indices, currently one of the bottlenecks for quadrature compilers with complex equations. (see expand_indices2, almost working)
      within some partitions and forward mode to connect them

# Derivatives (low priority):
    Forward mode AD seems to work well. More validation is always welcome though.
    - Finish reverse mode AD implementation and compare performance
      (implement after orthotropic hyperelasticity is validated)
    - The best is probably a mix of the two, using reverse mode

# Mappings:
    - This is cut from the old WIKI pages:
            Alternatives for basis function mapping:
            * mapping = "affine"
            * mapping = "isoparametric"
            * mapping = "Piola" (FIXME: how to handle covariant/contravariant/symmetric Piola here?)
      Should they be attached to the cell or the elements?

# Functions on subdomains:
    - Function(element, domain=dx(0))
    - BasisFunction(element, domain=dx(1))

# Additional operators:
    - tan(f)
    - log(f, base)
    - other mathematical functions in <cmath> (need derivatives)

# Elements and Basisfunctions (medium/low priority, needed for some non-trivial applications):
    - (low) Implement
       class ElementUnion(FiniteElementBase):
           def __init__(self, *elements):
               ...
      to represent the enrichment of a finite element space with another. (Idea from Marie)
    - (low) Time elements

# Functions:
    - (low) Attaching derivatives to Functions:
      It would be nice if the user could supply the derivative of a Function as another Function.
      Maybe we can do:
   
        Df = Function(element2)
        f = Function(element1, gradient=Df)
   
      and perhaps for linearization:
   
        g = Function(element3)
        df_dg = Function(element2)
        f = Function(element1, derivatives = { g: df_dg })
   
      then you could do:
   
        F = derivative(f**2*dx, f)
        J = derivative(F, f)
   
      even if f is defined on a quadrature element.

# Time derivatives (low priority):
    - Do we want something like Dt(u), Dtt(u), CR(a), FE(a), BE(a), TR(a, theta)?
    - In particular, this can be interesting in combination with time elements?
        es = FiniteElement("CG", triangle, 1)
        et = TimeElement(1) # Any point in non-Galerkin elements?
        e = es*et
        v = TestFunction(e)
        u = TrialFunction(e)
        f = Function(es)
        g = Function(e)
        a = f*u*v*dx
      Need to extend ufc::cell for this, perhaps adding time interval [t0,t1] as part 
      of ufc::cell, new shapes time_triangle etc and bool is_time_dependent() to form.

# Complex numbers (low priority):
    - Allowing complex values and functions, which operations would be affected?
      Is it mostly about multiplication and division?

# Notes by Anders (trying to make sense of the implementation)

  OK   = Understand it and it looks ok
  OK!  = Understand it and it looks really good (done)
  ??   = Don't understand this module (yet)
  --   = Undecided
  hmm  = Skeptical
... (removed filenames here because they have changed quite a bit since the list was written)

