← Back to team overview

ufl team mailing list archive

Re: [HG UFL] Implemented __iter__ in Expr such that

 

On Mon, Apr 6, 2009 at 3:07 PM, Anders Logg <logg@xxxxxxxxx> wrote:
> On Mon, Apr 06, 2009 at 02:42:33PM +0200, Martin Sandve Aln=E6s wrote:
>> 2009/4/6 Johan Hake <hake@xxxxxxxxx>:
>> > On Monday 06 April 2009 13:44:14 Martin Sandve Aln=E6s wrote:
>> >> I'm not sure, I was just thinking about this...
>> >>
>> >> Say we have:
>> >>
>> >> =A0 V =3D VectorElement("CG", triangle, 1)
>> >> =A0 P =3D FiniteElement("CG", triangle, 1)
>> >> =A0 TH =3D V+P
>> >> =A0 up =3D Function(TH)
>> >>
>> >> then up.shape() =3D=3D (3,) and thus len(up) =3D=3D 3 and you can do
>> >>
>> >> =A0 ux, uy, p =3D up # only considers the value shape
>> >> =A0 u =3D as_vector((ux, uy))
>> >>
>> >> while ufl.split works like this:
>> >>
>> >> =A0 u, p =3D split(up) # deals with the mixed element structure
>> >> =A0 len(u) =3D=3D 2
>> >>
>> >> We can only implement __iter__ to do one thing!
>> >
>> > A naive solution could be to overload the __len__ and __iter__ function=
> s in
>> > ufl.Functions, so they return the subfunctions as they are used in spli=
> t()?
>>=20
>> Yes, that's the general idea, but then iteration over a Function and
>> another ufl expression won't work the same way. If that's what we
>> choose to do I will probably remove iteration over general expressions,
>> because this will be too confusing.
>
> If I do
>
>  TH = V + P
>  w = Function(TH)
>
> then I expect w to be vector-valued function of size d + 1.

Yes, nobody disagrees with that.


> So I suggest the split functionality to be a special call:
>
>  ux, uy, p = w

Ok, just like I just implemented __iter__ in UFL.
Requires that __iter__ is _not_ overloaded for Function in dolfin.

>  (ux, uy), p = w.split()

This line is not as innocent as it looks...

Consider these two lines:
A)  u, p = w.split()
B)  (ux, uy), p = w.split()

We already have (A), and it works fine.
B is like A plus this line:
C)  ux, uy = u

so B will _either_ need to use __iter__ on u for splitting u -> (ux,uy),
_or_ w.split() must already have returned a tuple(tuple(ux,uy), p),
in which case A will result in u being a tuple (which nobody wants).


Note that you didn't differentiate between ufl.split(w) and w.split(),
they are still not the same.


>> > I have __no__ clue what so ever to what other things this potentially c=
> ould
>> > break ;)
>>=20
>> For some reason I had explicitly implemented __iter__ using
>> NotImplemented to signal it shouldn't be used, and as I said
>> I don't remember why that was:
>>=20
>> >> It might be for ambiguities similar to this that I didn't
>> >> implement this earlier, but I don't remember any
>> >> more compelling reasons...
>>=20
>> >> In PyDOLFIN, Function.split() is something else?
>> >>
>> >> It creates SubFunctions, which can't be used in forms.
>> >> Right?
>> >
>> > As it is now you are actually able to use the returned subfunction to d=
> efine
>> > forms. It's a bug which I will fix :P.
>> >
>> > It turns out that the subfunctions has two version of the FunctionSpace=
> =2E One
>> > in python, which is just the original FunctionSpace that was used to de=
> fine
>> > the MixedFunctionSpace and one which is the correct FunctionSpace, incl=
> uding
>> > the correct offset, which is stored by the c++ version. Nice! Not...
>> >
>> > I will fix this so the versions correponds.
>>=20
>> I won't even try to wrap my head around that paragraph,
>> this is why I'm continuing to use C++ while getting UFL done :-/
>> (Don't waste your time trying to explain it better,
>> I just don't want to know at this point)
>>=20
>>=20
>> >> I think we should keep that explicit.
>> >
>> > While I see the ambiguity I implemented this in PyDOLFIN.
>> >
>> > Now in the stokes demo we can do:
>> >
>> > =A0u, p =3D problem.solve()
>> >
>> > This is what you thought of Anders? You desides what get pushed :)
>
> It looks good, but perhaps it should not be implemented using __iter__
> but instead the solve() function checks if there it is solving a mixed
> system and in that case calls split() before returning. So that it
> sometimes returns a single solution and sometimes a tuple. Or might
> that also be confusing?

We can't do that, because the user might want the solution function
in the mixed space for further use. There's no "un-split".


>> But what does this mean?
>>   u, p =3D ufl.split(up)
>> or
>>   u, p =3D up.split()
>> ?
>>=20
>> Unless there is a solution to make these the same (which seems
>> complicated), I still think this should be done explicitly.
>>=20
>> Also, I've said before: PyDOLFIN.Function should _not_ implement
>> any special functions (__foo__) since they may interfere with UFL.
>> The "u, p =3D up" feature breaks with this.
>
> I'm not sure that's an absolute rule. There may be exceptions.
> One such is __repr__.

Repr has a very specific meaning and should not be
implemented for dolfin.Function, because a proper
implementation of it would require a full string representation
of the mesh.

Repr is used for comparing objects many places in
UFL and as such is particularly important to _not_
overload. I said this several times before, and nobody
argued then. Feel free to overload __str__.

If you disagree with UFL design, please say so at ufl-dev.
Nobody has done so, and I can't read minds.

Martin


Follow ups

References