split(u) versus u.split()

Issue #194 new
Nico Schlömer created an issue

A constant source of confusion are the two split methods in DOLFIN/UFL. Behold:

V = FunctionSpace(mesh, 'CG', 1)
W = V*V

u = Function(W)

print split(u)
print u.split()

This inconsistency leads to errors like http://fenicsproject.org/qa/2273/stationary-navier-stokes-all-terms-form-must-have-same-rank.

This probably can't be called a bug, but I'd still propose to rename or remove one of the two.

Comments (22)

  1. Martin Sandve Alnæs

    It might be possible to fix this in a better way if we have a dolfin.FunctionView class which inherits from ufl.Indexed and carefully follows the right UFL protocols. Then by implementing Function.getitem properly, we can make f[int] return a FunctionView which UFL sees as an Indexed.

    This has to be scalar valued though; e.g. with a mixed vector-scalar function f we can't have f[0] mean the vector valued component of the first space, it has to be the first scalar component. A possible fix for that is to implement a new type in UFL to represent a sliced expression, such that f[0:d] can return something like a ufl.Sliced(f, ufl.Slice(0,d)) in UFL and a dolfin.FunctionView in DOLFIN with dolfin.FunctionView inheriting from ufl.Sliced.

  2. Prof Garth Wells

    Having a FunctionView class would make what's going on in DOLFIN clearer to the user, and it would simplify some of the DOLFIN code.

  3. Martin Sandve Alnæs

    On the ufl side it might be possible to have a generic ufl.Sliced type, a more specific ufl.FunctionView type, or both. The consequences of that choice needs to be worked out later.

    I like the consistency of having MeshView and FunctionView in both dolfin and ufl.

  4. Jan Blechta

    Isn't this now easily solvable when Function inherits from both cpp.Function and ufl.Coefficient, @martinal?

  5. Martin Sandve Alnæs

    Function always did. What's needed is a (Sub)FunctionView type which represents a view into the data of Function. Also the operation myfunctionview = myfunction[index] must be cheap (that can be achieved by letting Function cache its component views).

  6. Anders Logg (Chalmers)

    I suggest letting split(u) and u[component] remain as the way to split a field into its component (UFL style) but add a function with another name for extracting components as Functions, perhaps extract_subfunctions.

    w = TrialFunction(W)
    u, p = split(w)
    
    w = Function(W)
    u, p = w.extract_subfunctions(deepcopy=True/False)
    
  7. Jan Blechta

    Minor sub issue report:

    from dolfin import *
    mesh = UnitSquareMesh(3, 3)
    V = VectorFunctionSpace(mesh, "P", 1)
    u = Function(V)
    u.split(u)
    

    The implicit conversion to bool should better be avoided.

  8. Prof Garth Wells

    Is the root of this issue from dolfin import *? If it was clear that one is ufl.split and the other is dolfin.Function.split, would the ambiguity be largely resolved? @martinal

  9. Miklós Homolya

    dolfin.Function.split is a member function of dolfin.Function, while ufl.split is a free function. The namespaces don't really matter.

  10. Jan Blechta

    The root of the problem is that some objects behave as ufl.Coefficient/Argument and dolfin.GenericFunction at the same time, creating nice abstraction for users, with no need to distinguish them, but there are two split functions behaving differently.

  11. Prof Garth Wells

    @blechta Multiple inheritance is not used in the pybind11 interface, which may simplify things.

    @miklos1 There is not technical problem, but when DOLFIN imports UFL functions behind the scenes users do not recognise the different origins.

  12. Miklós Homolya

    What I am saying is that it is very unpythonic to "import" class members. It is true, that in Python if isinstance(f, Function) then one may write f.split() as Function.split(f), but to "import" unbound instance methods directly is overly confusing in itself.

    The issue is rather that the same name is used with slightly different syntax and different meaning. In particular, ufl.split returns split functions that remember that they come from a mixed space, while dolfin.Function.split perhaps not.

  13. Log in to comment