The mesh module provides mesh generators: methods that return a topology and an accompanying geometry function. Meshes can either be generated on the fly, e.g. rectilinear(), or read from external an externally prepared file, gmsh(), and converted to nutils format. Note that no mesh writers are provided at this point.

nutils.mesh.rectilinear(richshape, periodic=(), name='rect')

rectilinear mesh

nutils.mesh.multipatch(patches, nelems, patchverts=None, name='multipatch')

multipatch rectilinear mesh generator

Generator for a MultipatchTopology and geometry. The MultipatchTopology consists of a set patches, where each patch is a StructuredTopology and all patches have the same number of dimensions.

The patches argument, a numpy.ndarray-like with shape (npatches, 2*ndims) or (npatches,)+(2,)*ndims, defines the connectivity by labelling the patch vertices. For example, three one-dimensional patches can be connected at one edge by:

# connectivity:     3
#                   │
#                1──0──2

patches=[[0,1], [0,2], [0,3]]

Or two two-dimensional patches along an edge by:

# connectivity:  3──4──5
#                │  │  │
#                0──1──2

patches=[[[0,3],[1,4]], [[1,4],[2,5]]]

The geometry is specified by the patchverts argument: a numpy.ndarray-like with shape (nverts,ngeomdims) specifying for each vertex a coordinate. Note that the dimension of the geometry may be higher than the dimension of the patches. The created geometry is a patch-wise linear interpolation of the vertex coordinates. If the patchverts argument is omitted the geometry describes a unit hypercube per patch.

The nelems argument is either an int defining the number of elements per patch per dimension, or a dict with edges (a pair of vertex numbers) as keys and the number of elements (int) as values, with key None specifying the default number of elements. Example:

# connectivity:  3─────4─────5
#                │ 4x3 │ 8x3 │
#                0─────1─────2

patches=[[[0,3],[1,4]], [[1,4],[2,5]]]
nelems={None: 4, (1,2): 8, (4,5): 8, (0,3): 3, (1,4): 3, (2,5): 3}

Since the patches are structured topologies, the number of elements per patch per dimension should be unambiguous. In above example specifying nelems={None: 4, (1,2): 8} will raise an exception because the patch on the right has 8 elements along edge (1,2) and 4 along (4,5).


An L-shaped domain can be generated by:

>>> # connectivity:  2──5
>>> #                │  |
>>> #                1──4─────7     y
>>> #                │  │     │     │
>>> #                0──3─────6     └──x
>>> domain, geom = multipatch(
...   patches=[[0,1,3,4], [1,2,4,5], [3,4,6,7]],
...   patchverts=[[0,0], [0,1], [0,2], [1,0], [1,1], [1,2], [3,0], [3,1]],
...   nelems={None: 4, (3,6): 8, (4,7): 8})

The number of elements is chosen such that all elements in the domain have the same size.

A topology and geometry describing the surface of a sphere can be generated by creating a multipatch cube surface and inflating the cube to a sphere:

>>> # connectivity:    3────7
>>> #                 ╱│   ╱│
>>> #                2────6 │     y
>>> #                │ │  │ │     │
>>> #                │ 1──│─5     │ z
>>> #                │╱   │╱      │╱
>>> #                0────4       *────x
>>> import itertools
>>> from nutils import function
>>> topo, cube = multipatch(
...   patches=[
...     [0,1,2,3], # left,   normal: x
...     [4,5,6,7], # right,  normal: x
...     [0,1,4,5], # bottom, normal: -y
...     [2,3,6,7], # top,    normal: -y
...     [0,2,4,6], # front,  normal: z
...     [1,3,5,7], # back,   normal: z
...   ],
...   patchverts=tuple(itertools.product(*([[-1,1]]*3))),
...   nelems=1)
>>> sphere = function.normalized(cube)

The normals of the patches are determined by the order of the vertex numbers. An outward normal for the cube is obtained by flipping the left, top and front faces:

>>> cubenormal = cube.normal(exterior=True) * topo.basis('patch').dot([-1,1,1,-1,-1,1])

At the centroids of the faces the outward normal should equal the cube geometry:

>>> numpy.testing.assert_allclose(*topo.sample('gauss', 1).eval([cubenormal, cube]))

Similarly, the outward normal of the sphere is obtained by:

>>> spherenormal = sphere.normal(exterior=True) * topo.basis('patch').dot([-1,1,1,-1,-1,1])
>>> numpy.testing.assert_allclose(*topo.sample('gauss', 1).eval([spherenormal, cube]))
  • patches – A numpy.ndarray with shape sequence of patches with each patch being a list of vertex indices.

  • patchverts – A sequence of coordinates of the vertices.

  • nelems – Either an int specifying the number of elements per patch per dimension, or a dict with edges (a pair of vertex numbers) as keys and the number of elements (int) as values, with key None specifying the default number of elements.



Gmsh parser

Parser for Gmsh data in msh2 or msh4 format. See the Gmsh manual for details.


mshdata (io.BufferedIOBase) – Msh file contents.


Keyword arguments for simplex()

Return type


nutils.mesh.gmsh(fname, name='gmsh')

Gmsh parser

Parser for Gmsh files in .msh format. Only files with physical groups are supported. See the Gmsh manual for details.

  • fname (str or io.BufferedIOBase) – Path to mesh file or mesh file object.

  • name (str or None) – Name of parsed topology, defaults to ‘gmsh’.


nutils.mesh.simplex(nodes, cnodes, coords, tags, btags, ptags, name='simplex')

Simplex topology.

  • nodes (numpy.ndarray) – Vertex indices as (nelems x ndims+1) integer array, sorted along the second dimension. This table fully determines the connectivity of the simplices.

  • cnodes (numpy.ndarray) – Coordinate indices as (nelems x ncnodes) integer array following Nutils’ conventions for Bernstein polynomials. The polynomial degree is inferred from the array shape.

  • coords (numpy.ndarray) – Coordinates as (nverts x ndims) float array to be indexed by cnodes.

  • tags (dict) – Dictionary of name->element numbers. Element order is preserved in the resulting volumetric groups.

  • btags (dict) – Dictionary of name->edges, where edges is a (nedges x 2) integer array containing pairs of element number and edge number. The segments are assigned to boundary or interfaces groups automatically while otherwise preserving order.

  • ptags (dict) – Dictionary of name->node numbers referencing the nodes table.

  • name (str) – Name of simplex topology.


nutils.mesh.fromfunc(func, nelems, ndims, degree=1)


nutils.mesh.unitsquare(nelems, etype)

Unit square mesh.

  • nelems (int) – Number of elements along boundary

  • etype (str) –

    Type of element used for meshing. Supported are:

    • "square": structured mesh of squares.

    • "triangle": unstructured mesh of triangles.

    • "mixed": unstructured mesh of triangles and squares.