split(u) versus u.split()
Issue #194 new
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.
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 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.
FunctionViewclass would make what's going on in DOLFIN clearer to the user, and it would simplify some of the DOLFIN code.
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.
See Issue #531.
Isn't this now easily solvable when
Functioninherits from both
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).
Removing milestone: 1.7 (automated comment)
I suggest letting
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
Minor sub issue report:
The implicit conversion to bool should better be avoided.
Is the root of this issue
from dolfin import *? If it was clear that one is
ufl.splitand the other is
dolfin.Function.split, would the ambiguity be largely resolved? @martinal
dolfin.Function.splitis a member function of
ufl.splitis a free function. The namespaces don't really matter.
The root of the problem is that some objects behave as
dolfin.GenericFunctionat the same time, creating nice abstraction for users, with no need to distinguish them, but there are two split functions behaving differently.
@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.
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
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.splitreturns split functions that remember that they come from a mixed space, while
We might want to ditch
Function.split()because there is caching behind the scene. See #531 (and #918).