Geometry, topology and tags#

cmap#

fenicsx_compat.cmap(mesh) -> dolfinx.fem.CoordinateElement

The coordinate element of the mesh geometry.

DOLFINx

Native

0.10

mesh.geometry.cmap

0.11, main

mesh.geometry.cmaps[0]. mesh.geometry.cmap still works but emits a DeprecationWarning.

cell = 0
nodes = mesh.geometry.x[fenicsx_compat.dofmap(mesh)[cell]]
X = fenicsx_compat.cmap(mesh).pull_back(np.array([[0.2, 0.1, 0.0]]), nodes)

dofmap#

fenicsx_compat.dofmap(mesh) -> numpy.ndarray

The geometry dofmap: the node indices of each cell, shape (num_cells, num_nodes_per_cell).

DOLFINx

Native

0.10

mesh.geometry.dofmap

0.11, main

mesh.geometry.dofmaps[0]. mesh.geometry.dofmap still works but emits a DeprecationWarning.

cell_nodes = mesh.geometry.x[fenicsx_compat.dofmap(mesh)]  # (num_cells, num_nodes_per_cell, 3)

meshtags_topology#

Added in version 0.2.0.

fenicsx_compat.meshtags_topology(tags) -> dolfinx.mesh.Topology

The topology a MeshTags is defined on, always as the Python dolfinx.mesh.Topology.

DOLFINx

tags.topology returns

Native Python topology

0.10, 0.11

the C++ topology

dolfinx.mesh.Topology(tags.topology)

main (DOLFINx PR #4350)

the Python topology

tags.topology

topology = fenicsx_compat.meshtags_topology(facet_tags)
cpp_topology = topology._cpp_object  # the C++ object, on every version

cell_permutation_info#

fenicsx_compat.cell_permutation_info(topology) -> numpy.ndarray  # uint32

Computes and returns the packed per-cell permutation info, ghost cells included, as used by dof transformations.

cell_info = fenicsx_compat.cell_permutation_info(mesh.topology)
# e.g. for V.element.Tt_inv_apply(data, cell_info, n)

Calling it is also the portable way to make sure the permutations are computed before handing the topology to code that needs them.

facet_permutations#

fenicsx_compat.facet_permutations(topology) -> numpy.ndarray  # uint8

The permutation of every facet of every cell, shape (num_cells, num_facets_per_cell), ghost cells included. These are the values FFCx kernels take as quadrature_permutation.

perms = fenicsx_compat.facet_permutations(mesh.topology)
perm = perms[cell, local_facet]

On main, an interval mesh gives an empty array, since points have no orientation.

create_facet_orientations#

Added in version 0.3.0.

fenicsx_compat.create_facet_orientations(topology) -> None

Computes the facet orientations that Raviart-Thomas and other contravariant Piola spaces need on a manifold. Call it on every rank, before creating the space.

DOLFINx

Native

0.10, 0.11

No equivalent, and none needed: such spaces are created without it. Does nothing.

main (DOLFINx PR #4625)

topology.create_facet_orientations(). Creating such a space on a manifold raises RuntimeError until it has been called.

submesh = dolfinx.mesh.create_submesh(mesh, 2, boundary_facets)[0]
fenicsx_compat.create_facet_orientations(submesh.topology)
V = dolfinx.fem.functionspace(submesh, ("RT", 1))

On main it raises ValueError for a topology whose dimension is not 2, as the native method does. Lagrange and Nédélec spaces do not need it.

submesh_to_parent#

Added in version 0.4.0.

fenicsx_compat.submesh_to_parent(entity_map, entities=None) -> numpy.ndarray

The parent entity of each of entities of a submesh, given one of the maps create_submesh returns (the entity map or the vertex map). Without entities, all local (owned and ghost) entities of the submesh are mapped.

DOLFINx

create_submesh returns the maps as

Native

0.10

arrays, the parent entity of each submesh entity

entity_map[entities]

0.11, main (DOLFINx PR #4140)

dolfinx.mesh.EntityMap

entity_map.sub_topology_to_topology(entities, inverse=False)

submesh, cell_map, vertex_map, _ = dolfinx.mesh.create_submesh(mesh, tdim, cells)
parent_cells = fenicsx_compat.submesh_to_parent(cell_map)
parent_vertices = fenicsx_compat.submesh_to_parent(vertex_map)

transfer_meshtags_to_submesh#

fenicsx_compat.transfer_meshtags_to_submesh(entity_tag, submesh, cell_to_parent, vertex_to_parent)
    -> dolfinx.mesh.MeshTags

Transfers tags on a parent mesh to a submesh created with dolfinx.mesh.create_submesh().

The two maps swapped places between 0.11 and main while keeping their names, so a positional call that is right on one version passes the maps the wrong way round on the other. That does not raise. The wrapper forwards by keyword, and takes the maps in the order create_submesh returns them:

submesh, cell_map, vertex_map, _ = dolfinx.mesh.create_submesh(mesh, tdim, cells)
sub_tags = fenicsx_compat.transfer_meshtags_to_submesh(cell_tags, submesh, cell_map, vertex_map)

If you call DOLFINx directly, pass both maps by keyword: cell_to_parent=cell_map, vertex_to_parent=vertex_map.