Package: dmsh
The worst mesh generator you'll ever use.Inspired bydistmesh, 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), andit produces pretty high-quality meshes.Combined withoptimesh, dmsh produces the
highest-quality 2D meshes in the west.ExamplesPrimitivesimportdmshimportmeshioimportoptimeshgeo=dmsh.Circle([0.0,0.0],1.0)X,cells=dmsh.generate(geo,0.1)# optionally optimize the meshX,cells=optimesh.optimize_points_cells(X,cells,"CVT (full)",1.0e-10,100)# visualize the meshdmsh.show(X,cells,geo)# and write it to a filemeshio.Mesh(X,{"triangle":cells}).write("circle.vtk")importdmshgeo=dmsh.Rectangle(-1.0,+2.0,-1.0,+1.0)X,cells=dmsh.generate(geo,0.1)importdmshgeo=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)CombinationsDifferenceimportdmshgeo=dmsh.Circle([-0.5,0.0],1.0)-dmsh.Circle([+0.5,0.0],1.0)X,cells=dmsh.generate(geo,0.1)importdmshgeo=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
circlec.importdmshimportnumpyasnpr=dmsh.Rectangle(-1.0,+1.0,-1.0,+1.0)c=dmsh.Circle([0.0,0.0],0.3)geo=r-cX,cells=dmsh.generate(geo,lambdapts:np.abs(c.dist(pts))/5+0.05,tol=1.0e-10)Unionimportdmshgeo=dmsh.Circle([-0.5,0.0],1.0)+dmsh.Circle([+0.5,0.0],1.0)X,cells=dmsh.generate(geo,0.15)importdmshgeo=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)importdmshimportnumpyasnpangles=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)Intersectionimportdmshgeo=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)importdmshimportnumpyasnpangles=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 theHalfSpaceprimtive for cutting off a circle.importdmshgeo=dmsh.HalfSpace([1.0,1.0])&dmsh.Circle([0.0,0.0],1.0)X,cells=dmsh.generate(geo,0.1)Rotation, translation, scalingimportdmshimportnumpyasnpgeo=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)importdmshgeo=dmsh.Rectangle(-1.0,+2.0,-1.0,+1.0)+[1.0,1.0]X,cells=dmsh.generate(geo,0.1)importdmshgeo=dmsh.Rectangle(-1.0,+2.0,-1.0,+1.0)*2.0X,cells=dmsh.generate(geo,0.1,tol=1.0e-5)Local refinementAll objects can be used to refine the mesh according to the distance to the object;
e.g. aPath:importdmshgeo=dmsh.Rectangle(0.0,1.0,0.0,1.0)p1=dmsh.Path([[0.4,0.6],[0.6,0.4]])deftarget_edge_length(x):return0.03+0.1*p1.dist(x)X,cells=dmsh.generate(geo,target_edge_length,tol=1.0e-10)Custom shapesIt is also possible to define your own geometry. Simply create a class derived fromdmsh.Geometrythat contains adistmethod and a method to project points onto the
boundary.importdmshimportnumpyasnpclassMyDisk(dmsh.Geometry):def__init__(self):self.r=1.0self.x0=[0.0,0.0]bounding_box=[-1.0,1.0,-1.0,1.0]feature_points=np.array([[],[]]).Tsuper().__init__(bounding_box,feature_points)defdist(self,x):assertx.shape[0]==2y=(x.T-self.x0).Treturnnp.sqrt(np.einsum("i...,i...->...",y,y))-self.rdefboundary_step(self,x):# project onto the circley=(x.T-self.x0).Tr=np.sqrt(np.einsum("ij,ij->j",y,y))return((y/r*self.r).T+self.x0).Tgeo=MyDisk()X,cells=dmsh.generate(geo,0.1)Debuggingdmsh is rather fragile, but sometimes the break-downs are due to an incorrectly defined
geometry. Usegeo.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.)Installationdmsh isavailable from the Python Package
Index, so simply typepip install dmshto install.TestingTo run the dmsh unit tests, check out this repository and typetox