-
Notifications
You must be signed in to change notification settings - Fork 160
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
EnsembleFunction
and friends.
#4025
base: master
Are you sure you want to change the base?
Conversation
|
|
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.
Sorry for all the nitpicks but this is a big addition to the API so we should try and follow what we claim are our best practices. In particular I think the docstrings need tweaking as per https://github.com/firedrakeproject/firedrake/wiki/Docstrings
@@ -0,0 +1,242 @@ | |||
from firedrake.petsc import PETSc |
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.
Missing __all__
(though I dislike the design pattern). You can avoid this by not using a wildcard import in ensemble/__init__.py
.
from .checkpointing import disk_checkpointing | ||
|
||
from functools import wraps | ||
|
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.
Missing __all__
Co-authored-by: Connor Ward <[email protected]>
Description
This PR introduces this abstraction to Firedrake as an
EnsembleFunction
representing the distributed mixed function, defined over aEnsembleFunctionSpace
, and anEnsembleCofunction
andEnsembleDualFunction
representing the dual objects.Why?
Methods that use the
Ensemble
will often involve something that looks like a mixed finite element function, where the subcomponents are distributed over the ensemble members. We need to treat the subcomponents asfiredrake.Functions
within each ensemble member, but also to have some collective semantics over the entire ensemble. See for example theAllAtOnceFunction
in asQ which represents a timeseries over an ensemble.Note that, whereas
firedrake.Function
does not allow nested mixed-ness, a particular component ofEnsembleFunction
can be mixed - this is essential for things like a timeseries of a mixed function, e.g. shallow water equations.Demo
At the bottom is a small script using the new objects to solve the heat equation with backward euler, parallel in time, with a block Jacobi preconditioner. It shows setting some typical usage including
Function
subcomponentsVec
EnsembleFunctionSpace
An
EnsembleFunction
is defined from anEnsembleFunctionSpace
, which just collects anEnsemble
with a list offiredrake.FunctionSpace
for each component on the local ensemble member. These are accessible throughEnsembleFunctionSpace.local_spaces
.The
EnsembleFunctionSpace
also has some handy utilities, e.g. adual
method, equality comparison, the number of dofs on the local rank, on the local ensemble member, and on the whole global function space.Currently the global list of subcomponents is not available, i.e. you cannot programmatically check from rank
i
whatFunctionSpace
is inEnsembleFunctionSpace.local_spaces
on rankj
, but I'm open to arguments for including this.EnsembleFunction
It's important to point out that this does not have any UFL symbolic information, i.e. it is data structure abstraction not a symbolic one. The subcomponents on the local ensemble member can be accessed as
firedrake.Functions
, with the usual UFL symbolic information, viaEnsembleFunction.subfunctions
.Equivalents to a few
firedrake.Function
arithmetic operations are implemented, e.g.assign
,zero
, and addition/multiplication overloads.A
PETSc.Vec
defined over theEnsemble.global_comm
for the data in all subcomponents on all ranks is accessed via context managersvec
,vec_ro
, andvec_wo
.Adjoint
Currently no
EnsembleFunction
operations are taped, so it cannot be used for adjoint problems in the same wayfiredrake.Function
can be.However, it does has the bare minimum
OverloadedType
functionality implemented to be usable as aControl
type, if you take responsibility for evaluating the tape (e.g. withEnsembleReducedFunctional
, or the 4DVar reduced functional in another PR).For example:
_ad_dot
- collective over the ensemble so it will DTRT withpyadjoint.taylor_test
and we should be able to remove thexfail
markers here._ad_to_list
and_ad_assign_numpy
so it will work with the pyadjoint interface to scipy optimize that relies onReducedFunctionalNumPy
._ad_{to,from}_petsc
so it can be used withTAO
.I'm planning on integrating
EnsembleFunction
withEnsembleReducedFunctional
in a subsequent PR.Implementation notes.
To build PETSc solvers over an
Ensemble
, what we need is a mechanism for glueing two types of operation over the same data together.firedrake.Function
objects on each ensemble member to evaluate local finite element operations.Vec
objects on the global comm which represent the global solution, to pass toKSP
,SNES
, etc.This is shown in the diagram below for an
EnsembleFunction
with 8 subcomponents, distributed equally over four ensemble members.firedrake.MixedFunctionSpace
(here).EnsembleFunction
creates afiredrake.Function
(called_full_local_function
) from this mixed function space to store all local subcomponents. These are the dark blue boxes in the diagram, each with two subcomponents in light blue.(The API is independent of the choice to use
MixedFunctionSpace
internally).EnsembleFunction.subfunctions
is a tuple offiredrake.Functions
that view the relevant components of_full_local_function.subfunctions
(see here). These are the light blue boxes on the right of the diagram, and will be the main way users interact with the data.For any elements of
EnsembleFunction.subfunctions
that are themselves mixed, we need to construct a newMixedDat
to view multiple components of_full_local_function.subfunctions
.Vec
accessed via theEnsembleFunction.vec
context managers is created over theEnsemble.global_comm
, and is shown in dark green on the left of the diagram. ThisVec
is created as a view over the data in the internal mixedfiredrake.Function
by passing_full_local_function.dat.vec.array
toVec.createWithArray
(here) (shown as the light green boxes).This means that for the data in
EnsembleFunction.vec
to be valid (the large dark green box), we need the data in_full_local_function.dat.vec
to be valid (the smaller light green box attached to the MixedFunction). To ensure this data is valid, we nest the_full_local_function.dat.vec
context managers inside theEnsembleFunction.vec
context managers here.One thing to be careful of, is that if the data in
_full_local_function.dat.vec
has been modified, (i.e. if the user has done anything withEnsembleFunction.subfunctions
!) then the data in the globalEnsembleFunction.vec
will have changed, but withoutEnsembleFunction.vec
knowing. This means we have to manually increase the state counter forEnsembleFunction.vec
andEnsembleFunction.vec_ro
.