-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fieldsplit: replace empty Forms with ZeroBaseForm #3947
base: master
Are you sure you want to change the base?
Conversation
|
|
cf743a1
to
be6a7b4
Compare
e0c7ba1
to
00b80e4
Compare
3f399e5
to
bf10f91
Compare
bf10f91
to
d82039d
Compare
730e299
to
35638df
Compare
35638df
to
3d06fc5
Compare
897cd3c
to
d6bb7dd
Compare
9c1c516
to
d6bb7dd
Compare
d7f0a1b
to
2a0c03b
Compare
firedrake/formmanipulation.py
Outdated
if len(indices) == 1: | ||
i = indices[0] | ||
W = V[i] | ||
W = DualSpace(W.mesh(), W.ufl_element()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use the subspace
function here too? It will need a switch adding for primal/dual but I think it would be nicer to use subspace
for both.
I think it would also be nice to lift subspace
out, possibly into one of the functionspace files. It's useful more generally - see for example line 678 in slate.py
where we have the same if/else block to construct the subspace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking to extend FunctionSpace.__getitem__
to allow a list index return the subspace, since this is how sub-arrays are extracted in numpy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The if statement can be avoided by using FunctionSpace.collapse()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was actually thinking exactly the same thing the other day.
It would be great to have it for Function
too so that you can get a Mixed
subfunction viewing the relevant subcomponents. ExtractSubBlock.cofunction
would then basically just be calling cofunction[idxs]
.
There are definitely other places where that would be useful too, for example in the EnsembleFunction
I've been working on here.
What does FunctionSpace.collapse()
do? It just looks like it would return a copy of the FunctionSpace
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ksagiyam what do you think about this __getitem__
idea? Currenty, indexing by a scalar returns IndexedProxyFunctionSpace
, but indexing by a list of a single item would return the collapsed version of this space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
__getitem__
for Function
is implemented in UFL so the changes would be needed there I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not too worried for the Function
case, that one seems more involved, as they are Expressions in the UFL sense, and extracting a component naturally means a scalar compoment, but here it seems that we want a MixedFunctionSpace (possibly vector-valued) component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could also be added to sub
or subfunctions
, although they both also have issues.
sub
explicitly says it is for bcs, and subfunctions
is already a tuple not a method so it would probably have to become a local class with __getitem__
overridden so we could deal with single or multiple indices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds slightly odd to me. Can you instead rewrite collapse()
so that it would take a list of indices as an optional argument?
@JHopeCollins collapse()
basically forgets parents. They do something nontrivial in ProxyFunctionSpace and in MixedFunctionSpace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok thanks.
It does strip the parent information, I don't think the name collapse
would be where I would look for this functionality - it would be more intuitive in subfunctions or sub.
@@ -135,6 +137,11 @@ def __init__(self, a, row_bcs=[], col_bcs=[], | |||
|
|||
self.action = action(self.a, self._x) | |||
self.actionT = action(self.aT, self._y) | |||
# TODO prevent action from returning empty Forms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this to do in this PR or at a later date? If it won't be part of this PR please can you open an issue for it to keep a record?
d46a06e
to
2eb6a56
Compare
firedrake/functionspaceimpl.py
Outdated
@@ -321,6 +321,14 @@ def __iter__(self): | |||
return iter(self.subfunctions) | |||
|
|||
def __getitem__(self, i): | |||
from firedrake.functionspace import MixedFunctionSpace | |||
if isinstance(i, list): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should allow any iterable, not just a list.
if isinstance(i, list): | |
if not isinstance(i, int): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to mimic numpy.array indexing. tuple
indices are used for multi-dimensional arrays, lists
give you sub-arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that matter here? This is to produce mixed subspaces so it will always be 1D. I don't think it introduces any confusion, and it makes the interface cleaner rather than having a superfluous list
at many call sites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the behaviour of __getitem__
is a bit subtle here. Calling obj[1, 2, 3]
is exactly the same as calling obj[(1, 2, 3)]
which is not quite the same as obj[[1, 2, 3]]
.
I think having something like space[1, 2]
would suggest to someone that space
is somehow nested, whereas space[[1, 2]]
suggests a subset of the indices.
@@ -321,6 +321,14 @@ def __iter__(self): | |||
return iter(self.subfunctions) | |||
|
|||
def __getitem__(self, i): | |||
from firedrake.functionspace import MixedFunctionSpace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should cache the mixed subspaces like we do for the non-mixed subspaces. Otherwise we get a "different" space every time we call with the same indices.
firedrake/functionspaceimpl.py
Outdated
# Return a collapsed subspace if the index is a list | ||
if len(i) == 1: | ||
return self[i[0]].collapse() | ||
else: | ||
return MixedFunctionSpace([self[isub] for isub in i]) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said elsewhere, I think this is odd. I feel we are abusing __getitem__()
. If we want this feature, we should do it somewhere else (in a new method or in collapse()
), not in __getitem__()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the call to collapse(), and will leave V[(i,)] == V[i]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So now V[(i,)]
is a non-collapsed indexed space and V[(i, j)]
is a new collapsed mixed space?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite. V[(i, )]
is no longer collapsed, which means that it is a IndexedProxyFunctionSpace
. But collapsing a MixedSpace
does nothing, as the new MixedSpace
subspace has lost any reference to the parent MixedSpace
. I only required collapsing the subspaces because Fieldsplit builds a new NLVP, and we cannot use proxy spaces for BCs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please read my comment carefully. I understand why we need this, but I have been claiming that we should not have __getitem__()
have multiple meanings depending on if we pass int
or tuple
/list
. If the former returns something which remembers the parent and the latter returns something which does not, it indicates that this feature should be implemented somewhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point, I hadn't quite appreciated whether the subspace remembers the parent or not. If I understand correctly then we currently have:
subfunction
(and by extension__getitem__
) returns aFunctionSpace
/Function
for a single subcomponent that remembers the parent.collapse
returns aFunctionSpace
/Function
with all components that forgets the parent.
What we want is a utility for returning a FunctionSpace
/Function
with some subcomponents that forgets the parent. The fact that it returns a subspace matches with subfunction
, but the fact that it forgets the parent matches with collapse
. This means that if we extend either of the existing methods then we will introduce some ambiguity into that method's purpose.
If we are to avoid this ambiguity then Koki is right, we need a new method given how important clarity is with symbolic information (e.g. the split
->subfunction
change).
This information should also be added to the docstrings for subfunctions
/sub
/__getitem__
/collapse
/the new method for all the FunctionSpace
classes plus the Function
classes and Cofunction
.
2eb6a56
to
934ff6f
Compare
Description
This PR addresses the consequences of FEniCS/ufl#336, which introduces more agressive simplifications that cause empty forms to be returned when extracting a subblock that is supposed to be zero (e.g. the pressure block in Stokes).
Here empty Jacobians are replaced with ZeroBaseForm, as we require two Arguments in order for the adjoint to make sense.
The simplifications should also speed up code generation and even reduce flop counts in some cases.