The meshgen module

The meshgen module conveniently produces high quality meshes for many kinds of domain. It follows the builder pattern with a MeshGen helper object that performs the construction. To use meshgen, the user must provide a scalar function that is positive everywhere that they want to be meshed.

Note One example is referred to in the literature as a signed distance function, which is the Euclidean distance of a given point \(x\) to the boundary of a set \(\Omega\) with the sign positive if \(x\) is in the interior of \(\Omega\). MeshGen does not require signed distance functions, but accepts any continuous and reasonably smooth function.

For example, the interior of the unit disk in two dimensions, is described by the function $$f(x,y)=1-(x^{2}+y^{2}).$$ To create the corresponding Mesh, we must first specify a suitable morpho function that describes the domain. This function will be called repeatedly by MeshGen, which will pass it a position vector x. Hence, the \((x,y)\) components must be accessed from the argument x by indexing:

fn disk(x) {
    return 1-(x[0]^2+x[1]^2)
}

Now that the function is specified, we can create a MeshGen object:

var mg = MeshGen(disk, [-1..1:0.2, -1..1:0.2])

The second parameter is a list of Ranges that provide overall bounds on the domain to be meshed. Here we will use \(x,y\in[-1,1]\). By setting the stepsize, the user can provide MeshGen with an overall suggestion of the resolution.

Finally, we create the Mesh by calling the build method:

var m = mg.build();

The resulting Mesh is shown in Fig. 5.1, left panel. A higher resolution Mesh can be generated by changing the Range objects passed to MeshGen:

var mg = MeshGen(disk, [-1..1:0.1, -1..1:0.1])

This generates a much higher resolution Mesh, with approximately four times the number of vertices as shown in Fig. 5.1, right panel.

imageimage

Two disks created with different resolutions with MeshGen.

MeshGen can also mesh more complicated domains. To facilitate this, it provides a Domain class that accepts a scalar function in its constructor. For example, this code creates an ellipse as shown in Fig. 5.2, left panel:

var e0 = Domain(fn (x) -((x[0]/2)^2+x[1]^2-1))
var mg = MeshGen(e0, [-2..2:0.2, -1..1:0.2])
var m = mg.build()

The benefit of this is that Domain objects can be combined using set operation methods union, intersection and difference. To illustrate the possibilities with this, we use a special constructor to create three domains corresponding to disks,

var a = CircularDomain(Matrix([-0.5,0]), 1)
var b = CircularDomain(Matrix([0.5,0]), 1)
var c = CircularDomain(Matrix([0,0]), 0.3)

then combine them,

var dom = a.union(b).difference(c)

and mesh the resulting domain,

var mg = MeshGen(dom, [-2..2:0.1, -1..1:0.1], quiet=false)
var m = mg.build()

with the result shown in Fig. 5.2, right panel.

imageimage

More complex domains can be created with MeshGen by combining domains.

Three dimensional meshes are created very similarly. Here we create a spherical mesh, displayed in Fig. 5.3

var dh = 0.2
var dom = Domain(fn (x) -(x[0]^2+x[1]^2+x[2]^2-1))
var mg = MeshGen(dom, [-1..1:dh, -1..1:dh, -1..1:dh])
var m = mg.build()
Spherical mesh created with MeshGen