# Topology vs Geometry

Rather than having a single concept of what is typically referred to as the
'mesh', Nutils maintains a strict separation of *topology* and *geometry*. The
`nutils.topology.Topology`

represents a collection of elements and
inter-element connectivity, along with recipes for creating bases. It has no
(public) notion of position. The geometry takes the `nutils.topology.Topology`

and positions it in space. This separation makes it possible to define
multiple geometries belonging to a single `nutils.topology.Topology`

, a feature
that is useful for example in certain Lagrangian formulations.

While not having mesh objects, Nutils does have a `nutils.mesh`

module, which
hosts functions that return tuples of topology and geometry. Nutils provides
two builtin mesh generators: `nutils.mesh.rectilinear`

, a generator for
structured topologies (i.e. tensor products of one or more one-dimensional
topologies), and `nutils.mesh.unitsquare`

, a unit square mesh generator with
square or triangular elements or a mixture of both. The latter is mostly
useful for testing. In addition to generators, Nutils also provides the
`nutils.mesh.gmsh`

importer for gmsh-generated meshes.

The structured mesh generator takes as its first argument a list of element vertices per dimension. A one-dimensional topology with four elements of equal size between 0 and 1 is generated by

```
mesh.rectilinear([[0, 0.25, 0.5, 0.75, 1.0]])
# (StructuredTopology<4>, Array<1>)
```

Alternatively we could have used `numpy.linspace`

to generate a sequence of
equidistant vertices, and unpack the resulting tuple:

```
topo, geom = mesh.rectilinear([numpy.linspace(0, 1, 5)])
```

We will use this topology and geometry throughout the remainder of this tutorial.

Note that the argument is a list of length one: this outer sequence lists the dimensions, the inner the vertices per dimension. To generate a two-dimensional topology, simply add a second list of vertices to the outer list. For example, an equidistant topology with four by eight elements with a unit square geometry is generated by

```
mesh.rectilinear([numpy.linspace(0, 1, 5), numpy.linspace(0, 1, 9)])
# (StructuredTopology<4x8>, Array<2>)
```

Any topology defines a boundary via the `nutils.topology.Topology.boundary`

attribute. Optionally, a topology can offer subtopologies via the getitem
operator. The rectilinear mesh generator automatically defines 'left' and
'right' boundary groups for the first dimension, making the left boundary
accessible as:

```
topo.boundary['left']
# StructuredTopology<>
```

Optionally, a topology can be made periodic in one or more dimensions by
passing a list of dimension indices to be periodic via the keyword argument
`periodic`

. For example, to make the second dimension of the above
two-dimensional mesh periodic, add `periodic=[1]`

:

```
mesh.rectilinear([numpy.linspace(0, 1, 5), numpy.linspace(0, 1, 9)], periodic=[1])
# (StructuredTopology<4x8p>, Array<2>)
```

Note that in this case the boundary topology, though still available, is empty.