Skip to content

Latest commit

 

History

History
258 lines (203 loc) · 9.53 KB

interop.rst

File metadata and controls

258 lines (203 loc) · 9.53 KB

Interoperability with Other Discretization Packages

Functionality in this subpackage helps import and export data to/from other pieces of software, typically PDE solvers.

Nodal DG

.. automodule:: meshmode.interop.nodal_dg

Firedrake

Function Spaces/Discretizations

Users wishing to interact with :mod:`meshmode` from :mod:`firedrake` will create a :class:`~meshmode.interop.firedrake.connection.FiredrakeConnection` using :func:`~meshmode.interop.firedrake.connection.build_connection_from_firedrake`, while users wishing to interact with :mod:`firedrake` from :mod:`meshmode` will use will create a :class:`~meshmode.interop.firedrake.connection.FiredrakeConnection` using :func:`~meshmode.interop.firedrake.connection.build_connection_to_firedrake`. It is not recommended to create a :class:`~meshmode.interop.firedrake.connection.FiredrakeConnection` directly.

.. automodule:: meshmode.interop.firedrake.connection

Meshes

.. automodule:: meshmode.interop.firedrake.mesh

Reference Cells

.. automodule:: meshmode.interop.firedrake.reference_cell


Implementation Details

Converting between :mod:`firedrake` and :mod:`meshmode` is in general straightforward. Some language is different:

Other than carefully tabulating how and which vertices/faces correspond to other vertices/faces/cells, there are two main difficulties.

  1. :mod:`meshmode` has discontinuous polynomial function spaces which may use different unit nodes than :mod:`firedrake`.
  2. :mod:`meshmode` requires that all mesh elements be positively oriented, :mod:`firedrake` does not. Meanwhile, when :mod:`firedrake` creates a mesh, it changes the element ordering and the local vertex ordering.

(1.) is easily handled by insisting that the :mod:`firedrake` :class:`~firedrake.functionspaceimpl.WithGeometry` uses polynomial elements and that the group of the :class:`~meshmode.discretization.Discretization` being converted is a :class:`~meshmode.discretization.poly_element.InterpolatoryQuadratureSimplexElementGroup` of the same order. Then, on each element, the function space being represented is the same in :mod:`firedrake` and :mod:`meshmode`. We may simply resample to one system or another's unit nodes.

To handle (2.), once we associate a :mod:`meshmode` element to the correct :mod:`firedrake` cell, we have something like this picture:

.. graphviz::

    digraph{
        // created with graphviz2.38 dot
        // NODES

        mmNodes [label="Meshmode\nnodes"];
        mmRef   [label="Meshmode\nunit nodes"];
        fdRef   [label="Firedrake\nunit nodes"];
        fdNodes [label="Firedrake\nnodes"];

        // EDGES

        mmRef -> mmNodes [label=" f "];
        fdRef -> fdNodes [label=" g "];
    }

(Assume we have already ensured that :mod:`meshmode` and :mod:`firedrake` use the same reference element by mapping :mod:`firedrake`'s reference element onto :mod:`meshmode`'s). If f=g, then we can resample function values from one node set to the other. However, if :mod:`firedrake` has reordered the vertices or if we flipped their order to ensure :mod:`meshmode` has positively-oriented elements, there is some map A applied to the reference element which implements this permutation of barycentric coordinates. In this case, f=g\circ A. Now, we have a connected diagram:

.. graphviz::

    digraph{
        // created with graphviz2.38 dot
        // NODES

        mmNodes [label="Meshmode\nnodes"];
        mmRef   [label="Meshmode\nunit nodes"];
        fdRef   [label="Firedrake\nunit nodes"];
        fdRef2  [label="Firedrake\nunit nodes"];
        fdNodes [label="Firedrake\nnodes"];

        // EDGES

        {rank=same; mmRef; fdRef;}
        {rank=same; mmNodes; fdNodes;}
        mmRef -> fdRef [label="Resampling", dir="both"];
        mmRef -> mmNodes [label=" f "];
        fdRef -> fdRef2 [label=" A "];
        fdRef2 -> fdNodes [label=" g "];
    }

In short, once we reorder the :mod:`firedrake` nodes so that the mapping from the :mod:`meshmode` and :mod:`firedrake` reference elements are the same, we can resample function values at nodes from one set of unit nodes to another (and then undo the reordering if converting function values from :mod:`meshmode` to :mod:`firedrake`). The information for this whole reordering process is stored in :attr:`~meshmode.interop.firedrake.connection.FiredrakeConnection.mm2fd_node_mapping`, an array which associates each :mod:`meshmode` node to the :mod:`firedrake` node found by tracing the above diagram (i.e. it stores g\circ A\circ \text{Resampling} \circ f^{-1}).

For Developers: Firedrake Function Space Design Crash Course

In Firedrake, meshes and function spaces have a close relationship. In particular, this is due to some structure described in this Firedrake pull request. If you wish to develop on / add to the implementation of conversion between :mod:`meshmode` and :mod:`firedrake`, you will need to understand their design style. Below is a crash course.

In short, it is the idea that every function space should have a mesh, and the coordinates of the mesh should be representable as a function on that same mesh, which must live on some function space on the mesh... etc. Under the hood, we divide between topological and geometric objects, roughly as so:

  1. A reference element defined using :mod:`finat` and :mod:`FIAT` is used to define what meshmode calls the unit nodes and unit vertices. It is worth noting that :mod:`firedrake` does not require a positive orientation of elements and that its reference triangle is different than specified in :mod:`modepy`.
  2. A ~firedrake.mesh.MeshTopology which holds information about connectivity and other topological properties, but nothing about geometry/coordinates etc.
  3. A class :class:`~firedrake.functionspaceimpl.FunctionSpace` created from a :mod:`finat` element and a ~firedrake.mesh.MeshTopology which allows us to define functions mapping the nodes (defined by the :mod:`finat` element) of each element in the ~firedrake.mesh.MeshTopology to some values. Note that the function :func:`~firedrake.functionspace.FunctionSpace` in the firedrake API is used to create objects of class :class:`~firedrake.functionspaceimpl.FunctionSpace` and :class:`~firedrake.functionspaceimpl.WithGeometry` (see (6)).
  4. A ~firedrake.function.CoordinatelessFunction (in the sense that its domain has no coordinates) which is a function in a :class:`~firedrake.functionspaceimpl.FunctionSpace`.
  5. A ~firedrake.mesh.MeshGeometry created from a :class:`~firedrake.functionspaceimpl.FunctionSpace` and a ~firedrake.function.CoordinatelessFunction in that :class:`~firedrake.functionspaceimpl.FunctionSpace` which maps each dof to its geometric coordinates.
  6. A :class:`~firedrake.functionspaceimpl.WithGeometry` which is a :class:`~firedrake.functionspaceimpl.FunctionSpace` together with a ~firedrake.mesh.MeshGeometry. This is the object returned usually returned to the user by a call to the :mod:`firedrake` function :func:`~firedrake.functionspace.FunctionSpace`.
  7. A :class:`~firedrake.function.Function` is defined on a :class:`~firedrake.functionspaceimpl.WithGeometry`.

Thus, by the coordinates of a mesh geometry we mean

  1. On the hidden back-end: a ~firedrake.function.CoordinatelessFunction f on some function space defined only on the mesh topology.
  2. On the front-end: A :class:`~firedrake.function.Function` with the values of f but defined on a :class:`~firedrake.functionspaceimpl.WithGeometry` created from the :class:`~firedrake.functionspaceimpl.FunctionSpace` f lives in and the ~firedrake.mesh.MeshGeometry f defines.

Basically, it's this picture (where a\to b if b depends on a)

Warning

In general, the :class:`~firedrake.functionspaceimpl.FunctionSpace` of the coordinates function of a :class:`~firedrake.functionspaceimpl.WithGeometry` may not be the same :class:`~firedrake.functionspaceimpl.FunctionSpace` as for functions which live in the :class:`~firedrake.functionspaceimpl.WithGeometry`. This picture only shows how the class definitions depend on each other.

.. graphviz::

    digraph{
        // created with graphviz2.38 dot
        // NODES

        top [label="Topological\nMesh"];
        ref [label="Reference\nElement"];
        fspace [label="Function Space"];
        coordless [label="Coordinateless\nFunction"];
        geo [label="Geometric\nMesh"];
        withgeo [label="With\nGeometry"];

        // EDGES

        top -> fspace;
        ref -> fspace;

        fspace -> coordless;

        top -> geo;
        coordless -> geo [label="Mesh\nCoordinates"];

        fspace -> withgeo;
        geo -> withgeo;
    }