Skip to content

Conversation

pefarrell
Copy link
Contributor

Description

This PR adds support for deflation in Firedrake via a custom SNES solver (firedrake.DeflatedSNES) and an object storing the solutions to be deflated (firedrake.Deflation). Deflation is a numerical technique for computing multiple solutions of a nonlinear problem. A general introduction to the idea can be found in

https://pefarrell.org/files/talks/deflation.pdf

This PR adapts and updates some code I've had in defcon (https://bitbucket.org/pefarrell/defcon) for many years.

The user interface can be seen in the tests in this PR, but the basic idea is sketched below.

    deflation = Deflation()  # by default, deflate no solutions
    appctx = {"deflation": deflation}

    # Find the first solution
    u.interpolate(guess)
    solver = NonlinearVariationalSolver(problem, solver_parameters=sp, appctx=appctx)
    solver.solve()

    # Now deflate the first solution found, restore initial guess, and
    # find second solution
    first = Function(u)
    deflation.append(first)
    u.interpolate(guess)  # start from the same initial guess as before
    solver.solve()  # if this converges, it converges to something different

The VI support requires a small PR in petsc4py to wrap SNESVIGetVariableBounds, which I will submit presently.

@pefarrell
Copy link
Contributor Author

The petsc4py MR is at https://gitlab.com/petsc/petsc/-/merge_requests/8701.

@pefarrell
Copy link
Contributor Author

The petsc4py MR has now been merged to PETSc main.

deflation = self.deflation

if self.snes.getType().startswith("vi"):
vi_inact = self.snes.getVIInactiveSet()
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we store this method as an attribute to avoid the weakref?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I confess I don't understand. Won't that keep a strong reference?

op = lambda x, y: inner(x - y, x - y)*dx
self.op = op

self.append = self.roots.append
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this still necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's convenient to have, if not necessary.

There is no documentation on how to make things work in complex mode,
so I don't know where to add conjugation so that complex mode is happy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants