* Cleanups needed for renaming Function --> Coefficient
* Cleanups needed for renaming BasisFunction --> Function



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

############# Priority features for next release:

    - Check for mixed linear/bilinear form when making FormData.

    - Make derivative handle subfunctions better


############# Unprioritized features:

    #from ufl import validate # TODO: Implement some generic function like validate that encompasses all validation that we can do in general for both elements, expressions, and forms.


# Tests (for code health and stability):
    - Write more unit tests!
    - In particular write tests for the core algorithms, ideally covering all operators.

# Assertions (for a better user experience):
    - Improve error checks and assertions in code.
    - Improve error recovery and reporting mechanism (can for example look at stack to determine context?)
    - Rewrite/improve all error messages (collect strings in separate file?)

# Documentation (for getting users started faster with less problems):
    - Improve operator docstrings (use epydoc @param and @return for the more complicated functions)
    - Improve manual.

# Pretty printing (for easier debugging and better support for code generation):
    - Finish precedence list to improve parenthesis use in __str__ and __repr__ and ufl2latex.
    - Implement C renderer
    - 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 (keeping the code healthy):
    - 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, i.e. such that expand_compounds and
      expand_derivatives can be applied multiple times with no additional
      performance penalty.

    - (hopefully not...) If AD needs to be applied in a compiler context, we need a
      framework for representing unapplied form transformations.

# Improved derivative computations (important only if critical bottlenecks are found):
    Forward mode AD seems to work well.
    More validation is always welcome though.
    Finish reverse mode AD implementation and compare performance.
    The best might be a mix of forward and reverse.

# Optimization of ufl run time (important only if 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

# Simplification of expressions (important only if critical bottlenecks are found):
    - 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...
      IT IS VERY IMPORTANT TO HAVE A GOOD AND __COMPLICATED__
      SET OF TESTS IN PLACE BEFORE DOING THIS!

# Handle zero valued forms:
    If form simplification renders a form empty, it should add a zero term such
    that the form can be assembled.
    Some examples:
      L = (0*v)*dx --> (0)*dx --> (0*v)*dx
      L = g*v*dx + 0*v*dx -> g*v*dx
      L = 0*v*dx + 0*g*v*dx -> (0*v)*dx
      L = 0*v*very_long_ufl_expression*dx -> (0*v)*dx


############# Unprioritized language features:

# Algorithms (medium priority, better analysis enables better form compiler results):
    - Improve algorithm for computing worst case quadrature degree with more rules

    - Implement algorithm to determine whether or not a bilinear form is self-adjoint (symmetric).
      Pseudo-steps for such an algorithm could be:
          def canonical_form(expression):
              return expression transformed to a truly canonical form, i.e. a representation that is completely unique
          self_adjoint = True
          for each integrand:
              a = canonical_form(integrand)
              b = canonical_form(replace(integrand, {v:u}))
              if not a == b:
                  self_adjoint = False
                  break

# Functions on subdomains (medium priority, several people have requested something like this):
    - Function(element, domain=dx(0))
    - BasisFunction(element, domain=dx(1))

# Elements (low priority):
    - (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 priority, could allow automatic linearization w.r.t. functions not in a finite element space?):
    - (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.

# Additional operators (low priority):
    - tan(f)
    - log(f, base)
    - other mathematical functions in <cmath> (need derivatives)
    - bessel functions (needs non-standard library code)

# Geometry mappings (low priority):
    - Specification of geometry mapping in Cell?
      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?)

# Improved conditionals (low priority, no use until basic conditionals are supported by form compilers):
    - Implement AND/OR

# 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)

