Firedrake connection
This creates a new submodule meshmode.interop
to interface with Firedrake. The content is an adaption of https://github.com/benSepanski/fd2mm so that hopefully we can write something like
from meshmode.interop.firedrake import FiredrakeConnection
V = FunctionSpace("DG", fdrake_mesh, 4)
fdrake_conn = FiredrakeConnection(cl_ctx, V)
# defines from_fdrake.discr, from_fdrake.discr.mesh
u_fdrake = interpolate(V, ...)
u_mm = fdrake_conn.from_firedrake(u_fdrake)
u_2_fdrake = fdrake_conn.to_firedrake(u_mm)
interop
works with two primary classes, ExternalImportHandler
and ExternalExportHandler
. I've only done Import handlers since I've been working firedrake
-> meshmode
. In either case, they are bare classes with a data
attribute that is used to implement __eq__
, __hash__
, etc.
I implemented ExternalImportHandler
s for several FInAT
, fiat
, and firedrake
classes. interop
's organization follows Firedrake's, which makes the conversion process a lot easier. Firedrake has a non-obvious function space organization detailed in this firedrake pull request. The tl;dr is:
- Reference elements are handled by
FInAT
/fiat
. These are used to determine unit nodes, firedrake meshes only use vertices - A
MeshTopology
which stores only connectivity information of vertices, no coordinates etc. - A
FunctionSpace
built from aMeshTopology
andFInAT
element used to define functions whose domain have no coordinates - A
CoordinatelessFunction
(i.e. its domain is coordinateless) which lives in someFunctionSpace
- A
MeshGeometry
created from someMeshTopology
t
and aCoordinatelessFunction
which lives in aFunctionSpace
defined ont
mapping each point to its coordinates- Some data is cached on the
MeshTopology
infiredrake
. For us, the shared data lives on aMeshGeometry
. This way,ExternalImportHandler
s for two different function spaces on the same mesh don't duplicate too much work (this comes up more than you would think sincefiredrake
makes you create different function spaces if your range is a vector instead of a scalar)
- Some data is cached on the
- A
WithGeometry
... this is what thefiredrake
functionFunctionSpace
really creates. It is aFunctionSpace
which lives on aMeshGeometry
. - A
Function
can be defined on aWithGeometry
Each of these data structures has a corresponding ExternalImportHandler
in meshmode.interop
that takes the firedrake
data and transforms it into the requisite form for meshmode
(e.g. handling different reference elements, unit node locations, element orientations, creating node/facial adjacency objects, copying over boundary tags).
All of the above organization is for the developer. A user would be using the FiredrakeConnection
class in meshmode/interop/firedrake/__init__.py
. This connection is created from a firedrake
function space and allows transporting functions back and forth from a corresponding meshmode
discretization.
Nb:
- We should be sure the
ExternalImportHandler
/ExternalExportHandler
structure is what we want since it will affect any future development ininterop
- There is some cleanup still to do, but I wanted to see what people thought of the overall design before I get into the details