Skip to content
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

Fix fieldsplit with Cofunction right hand side. #3932

Merged
merged 12 commits into from
Jan 2, 2025

Conversation

JHopeCollins
Copy link
Member

Problem description

As described in #3368, it currently isn't possible to use PCFieldsplit if the form contains a Cofunction.
This is because the way we split the form is by traversing the dag with a ufl.MultiFunction and splitting each node as it is visited. However, none of the current handlers will deal with a Cofunction.

This PR adds a Cofunction handler to the ExtractSubBlock multifunction to do this splitting.
Fixes #3368

What does the Cofunction handler need to achieve?

A fieldsplit solver needs the right hand side from the corresponding field. For a Cofunction this means the values in the corresponding subfunction. So when we split a form the return value needs to live in the correct subspace, and point to the numerical values from the full space.

How is this implemented?

If all terms in the form have 1 argument (i.e. a FormSum of Cofunctions and 1-forms), then life is simple. We just check which field(s) is being requested, and make a new Cofunction in that (possibly mixed) subspace using the Dats from the original Cofunction.

If some terms in the full Form have 2 arguments, then life is a little more complicated, and we have two possibilities.

  1. If we're being asked for a block on the diagonal, then a) numerically this is probably going to be inverted and so needs a right hand side and b) mathematically this acts on a member of a function space and returns an assembled thing in the dual space - this is exactly what the Cofunction is (I'm jetlagged and I've probably slaughtered the dual/primal space technicalities. Edits to fix the explanation welcome). In this case we do the same as for the 1-form case i.e. we just make a new smaller Cofunction that views the appropriate parts of the full Cofunction.

  2. If we're being asked for an off-diagonal block, then a) numerically this doesn't make sense to invert and hence to have a right hand side, and b) mathematically the test and trial spaces are different, which doesn't make sense to have a corresponding Cofunction (I think?). In this case we just return a ZeroBaseForm which will get optimised out before we do any actual computational work.

Other changes

Because we can now split a Cofunction or FormSum, not just a Form, I had to widen the logic in split_form for checking if the form returned by ExtractSubBlock is empty or not. It works but it might not be the best/most robust way of checking.

What if this all breaks in the future?

There's a test that solves a mixed formulation of the wave equation using a Schur factorisation with both a 1-form right hand side and an equivalent Cofunction right hand side, and checks the results match close to machine precision.
The Schur complement is built by asking PETSc to do the brute force thing. Computationally suboptimal but the mesh is tiny, it reduces the amount of other "stuff" needed, and testing implementations is basically what the brute force thing is for.

@JHopeCollins
Copy link
Member Author

@stephankramer I see that you were also having issues with this in thetisproject/thetis#376. If you/someone else from the Thetis team could checkout this branch and make sure it fixes things for you then that would be really helpful.

Copy link

github-actions bot commented Dec 16, 2024

TestsPassed ✅Skipped ⏭️Failed ❌
Firedrake real8159 ran7484 passed675 skipped0 failed

Copy link

github-actions bot commented Dec 16, 2024

TestsPassed ✅Skipped ⏭️Failed ❌
Firedrake complex8153 ran6679 passed1474 skipped0 failed

firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
tests/firedrake/regression/test_fieldsplit_cofunction.py Outdated Show resolved Hide resolved
tests/firedrake/regression/test_fieldsplit_cofunction.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
firedrake/formmanipulation.py Outdated Show resolved Hide resolved
Copy link
Contributor

@connorjward connorjward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@JHopeCollins
Copy link
Member Author

@pbrubeck unless you have any other issues I'd like to merge this PR.

@pbrubeck pbrubeck enabled auto-merge (squash) January 2, 2025 13:12
@JHopeCollins JHopeCollins dismissed pbrubeck’s stale review January 2, 2025 14:10

all suggestions addressed

@pbrubeck pbrubeck merged commit bfb7a19 into master Jan 2, 2025
20 checks passed
@pbrubeck pbrubeck deleted the JHopeCollins/cofunction_fieldsplit branch January 2, 2025 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: Fieldsplit doesn't work with a Cofunction right hand side.
4 participants