The worst mesh generator you'll ever use.
Inspired by distmesh, dmsh can be slow, requires a lot of memory, and isn't terribly robust either.
On the plus side,
- it's got a user-friendly interface,
- is pure Python (and hence easily installable on any system), and
- it produces pretty high-quality meshes.
Combined with optimesh, dmsh produces the highest-quality 2D meshes in the west.
Examples
Primitives
import dmsh
import meshio
import optimesh
geo = dmsh.Circle([0.0, 0.0], 1.0)
X, cells = dmsh.generate(geo, 0.1)
# optionally optimize the mesh
X, cells = optimesh.optimize_points_cells(X, cells, "CVT (full)", 1.0e-10, 100)
# visualize the mesh
dmsh.show(X, cells, geo)
# and write it to a file
meshio.Mesh(X, {"triangle": cells}).write("circle.vtk")
import dmsh
geo = dmsh.Rectangle(-1.0, +2.0, -1.0, +1.0)
X, cells = dmsh.generate(geo, 0.1)
import dmsh
geo = dmsh.Polygon(
[
[0.0, 0.0],
[1.1, 0.0],
[1.2, 0.5],
[0.7, 0.6],
[2.0, 1.0],
[1.0, 2.0],
[0.5, 1.5],
]
)
X, cells = dmsh.generate(geo, 0.1)
Combinations
Difference
import dmsh
geo = dmsh.Circle([-0.5, 0.0], 1.0) - dmsh.Circle([+0.5, 0.0], 1.0)
X, cells = dmsh.generate(geo, 0.1)
import dmsh
geo = dmsh.Circle([0.0, 0.0], 1.0) - dmsh.Polygon([[0.0, 0.0], [1.5, 0.4], [1.5, -0.4]])
X, cells = dmsh.generate(geo, 0.1, tol=1.0e-10)
The following example uses a nonconstant edge length; it depends on the distance to the
circle c.
import dmsh
import numpy as np
r = dmsh.Rectangle(-1.0, +1.0, -1.0, +1.0)
c = dmsh.Circle([0.0, 0.0], 0.3)
geo = r - c
X, cells = dmsh.generate(geo, lambda pts: np.abs(c.dist(pts)) / 5 + 0.05, tol=1.0e-10)
Union
import dmsh
geo = dmsh.Circle([-0.5, 0.0], 1.0) + dmsh.Circle([+0.5, 0.0], 1.0)
X, cells = dmsh.generate(geo, 0.15)
import dmsh
geo = dmsh.Rectangle(-1.0, +0.5, -1.0, +0.5) + dmsh.Rectangle(-0.5, +1.0, -0.5, +1.0)
X, cells = dmsh.generate(geo, 0.15)
import dmsh
import numpy as np
angles = np.pi * np.array([3.0 / 6.0, 7.0 / 6.0, 11.0 / 6.0])
geo = dmsh.Union(
[
dmsh.Circle([np.cos(angles[0]), np.sin(angles[0])], 1.0),
dmsh.Circle([np.cos(angles[1]), np.sin(angles[1])], 1.0),
dmsh.Circle([np.cos(angles[2]), np.sin(angles[2])], 1.0),
]
)
X, cells = dmsh.generate(geo, 0.15)
Intersection
import dmsh
geo = dmsh.Circle([0.0, -0.5], 1.0) & dmsh.Circle([0.0, +0.5], 1.0)
X, cells = dmsh.generate(geo, 0.1, tol=1.0e-10)
import dmsh
import numpy as np
angles = np.pi * np.array([3.0 / 6.0, 7.0 / 6.0, 11.0 / 6.0])
geo = dmsh.Intersection(
[
dmsh.Circle([np.cos(angles[0]), np.sin(angles[0])], 1.5),
dmsh.Circle([np.cos(angles[1]), np.sin(angles[1])], 1.5),
dmsh.Circle([np.cos(angles[2]), np.sin(angles[2])], 1.5),
]
)
X, cells = dmsh.generate(geo, 0.1, tol=1.0e-10)
The following uses the HalfSpace primtive for cutting off a circle.
import dmsh
geo = dmsh.HalfSpace([1.0, 1.0]) & dmsh.Circle([0.0, 0.0], 1.0)
X, cells = dmsh.generate(geo, 0.1)
Rotation, translation, scaling
import dmsh
import numpy as np
geo = dmsh.Rotation(dmsh.Rectangle(-1.0, +2.0, -1.0, +1.0), 0.1 * np.pi)
X, cells = dmsh.generate(geo, 0.1, tol=1.0e-10)
import dmsh
geo = dmsh.Rectangle(-1.0, +2.0, -1.0, +1.0) + [1.0, 1.0]
X, cells = dmsh.generate(geo, 0.1)
import dmsh
geo = dmsh.Rectangle(-1.0, +2.0, -1.0, +1.0) * 2.0
X, cells = dmsh.generate(geo, 0.1, tol=1.0e-5)
Local refinement
All objects can be used to refine the mesh according to the distance to the object;
e.g. a Path:
import dmsh
geo = dmsh.Rectangle(0.0, 1.0, 0.0, 1.0)
p1 = dmsh.Path([[0.4, 0.6], [0.6, 0.4]])
def target_edge_length(x):
return 0.03 + 0.1 * p1.dist(x)
X, cells = dmsh.generate(geo, target_edge_length, tol=1.0e-10)
Custom shapes
It is also possible to define your own geometry. Simply create a class derived from
dmsh.Geometry that contains a dist method and a method to project points onto the
boundary.
import dmsh
import numpy as np
class MyDisk(dmsh.Geometry):
def __init__(self):
self.r = 1.0
self.x0 = [0.0, 0.0]
bounding_box = [-1.0, 1.0, -1.0, 1.0]
feature_points = np.array([[], []]).T
super().__init__(bounding_box, feature_points)
def dist(self, x):
assert x.shape[0] == 2
y = (x.T - self.x0).T
return np.sqrt(np.einsum("i...,i...->...", y, y)) - self.r
def boundary_step(self, x):
# project onto the circle
y = (x.T - self.x0).T
r = np.sqrt(np.einsum("ij,ij->j", y, y))
return ((y / r * self.r).T + self.x0).T
geo = MyDisk()
X, cells = dmsh.generate(geo, 0.1)
Debugging
dmsh is rather fragile, but sometimes the break-downs are due to an incorrectly defined geometry. Use
geo.show()
to inspect the level set function of your domain. (It must be negative inside the domain and positive outside. The 0-level set forms the domain boundary.)
Installation
dmsh is available from the Python Package Index, so simply type
pip install dmsh
to install.
Release files for dmsh 0.3.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| dmsh-0.3.8-cp314-none-any.whl | CPython 3.14 | none | any | Details |
| dmsh-0.3.8-cp313-none-any.whl | CPython 3.13 | none | any | Details |
| dmsh-0.3.8-cp312-none-any.whl | CPython 3.12 | none | any | Details |
| dmsh-0.3.8-cp311-none-any.whl | CPython 3.11 | none | any | Details |
| dmsh-0.3.8-cp310-none-any.whl | CPython 3.10 | none | any | Details |
Total release size: 468.2 kB
Release files / dmsh-0.3.8-cp314-none-any.whl
| Download URL | dmsh-0.3.8-cp314-none-any.whl |
|---|---|
| Size | 103.6 kB |
| Tags | CPython 3.14 |
|
SHA-256 checksum How to use checksums |
f3eb6c9f051ba0f53bcd1def46b251afe5e9ede10f0f44877df5c39db6cc73db
|
|
BLAKE2b-256 checksum How to use checksums |
9bb69c0e3249d724fc6f6690452ac7801f40acc273d9d37f8eed20fa1601baa7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency logRelease files / dmsh-0.3.8-cp313-none-any.whl
| Download URL | dmsh-0.3.8-cp313-none-any.whl |
|---|---|
| Size | 99.3 kB |
| Tags | CPython 3.13 |
|
SHA-256 checksum How to use checksums |
5a109ecd92ecfbe2d3bee130d2056a4c77753cedc384852683aecaa6ba31cf2e
|
|
BLAKE2b-256 checksum How to use checksums |
6a7eb8c4fae84a8d407d0d43db32bd84dadca7ec2fc1218f403cfb1324cb17c2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency logRelease files / dmsh-0.3.8-cp312-none-any.whl
| Download URL | dmsh-0.3.8-cp312-none-any.whl |
|---|---|
| Size | 99.1 kB |
| Tags | CPython 3.12 |
|
SHA-256 checksum How to use checksums |
56674037b1ae0fe64fb00efda91103360ac570ff448a78f0b2270dbb6fa910e2
|
|
BLAKE2b-256 checksum How to use checksums |
20410fbce2f33a295eab9c90ba3ddab24c4706b312e9c13926b85ff592d5f0e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency logRelease files / dmsh-0.3.8-cp311-none-any.whl
| Download URL | dmsh-0.3.8-cp311-none-any.whl |
|---|---|
| Size | 108.8 kB |
| Tags | CPython 3.11 |
|
SHA-256 checksum How to use checksums |
cb6dc559fd349c3d44d2a43e6b7c1f2834ff237d3aaff8f9ad78a48f49d77b2c
|
|
BLAKE2b-256 checksum How to use checksums |
c3feca683e8eec88749e3cb549368fce98277e394208ceada013c8422fd78b5a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency logRelease files / dmsh-0.3.8-cp310-none-any.whl
| Download URL | dmsh-0.3.8-cp310-none-any.whl |
|---|---|
| Size | 57.4 kB |
| Tags | CPython 3.10 |
|
SHA-256 checksum How to use checksums |
45366706a2fe245594c9e123ac061871019bd82f6807d72dde56133570e593e3
|
|
BLAKE2b-256 checksum How to use checksums |
3e21a1f8c20f5048e3704e37ada7bc21b5f77dadd4d12dd55093c442ce300e02
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency log