Skip to content

Firedrake connection

Ben Sepanski requested to merge ben_sepanski/meshmode:firedrakeConnection into master

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 ExternalImportHandlers 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 a MeshTopology and FInAT element used to define functions whose domain have no coordinates
  • A CoordinatelessFunction (i.e. its domain is coordinateless) which lives in some FunctionSpace
  • A MeshGeometry created from some MeshTopology t and a CoordinatelessFunction which lives in a FunctionSpace defined on t mapping each point to its coordinates
    • Some data is cached on the MeshTopology in firedrake. For us, the shared data lives on a MeshGeometry. This way, ExternalImportHandlers for two different function spaces on the same mesh don't duplicate too much work (this comes up more than you would think since firedrake makes you create different function spaces if your range is a vector instead of a scalar)
  • A WithGeometry... this is what the firedrake function FunctionSpace really creates. It is a FunctionSpace which lives on a MeshGeometry.
  • A Function can be defined on a WithGeometry

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 in interop
  • 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

Merge request reports