# Element Mesh Generation

In order to use mesh generation functionality, the finite element method (FEM) package needs to be loaded.

 In[1]:=

## Introduction

Many numerical solution techniques work by replacing a region of interest with an approximation of that region. This approximation is called a discrete region. The discrete region is partitioned into a collection of smaller elements that, as a sum, make up the entire discrete region. This partitioned discrete region is called a mesh. Finding the numerical solution is then based on computing the solution on the smaller elements and then combining the partial solutions into a solution over the entire mesh.

NDSolve, for example, internally converts the region into an ElementMesh object. This ElementMesh is a discrete, approximate version of the region over which the numerical analysis is conducted. Numerical functions such as NDSolve are capable of receiving an ElementMesh as input instead of the symbolic region description. This gives great flexibility over the mesh generation process; the element mesh, in fact, could have been generated by an external tool, for example.

There are various ways to create an ElementMesh, and various functions are provided to assist during the mesh creation process. The main function to create an ElementMesh is called ToElementMesh. ToElementMesh allows for various conceptually different methods to create an ElementMesh:

• implicit mesh creation
• explicit creation

Implicit element mesh creation is based on converting an implicit function such as an ImplicitRegion to an ElementMesh. By contrast, explicit mesh generation is based on converting an explicit representation such as a GraphicsComplex into an element mesh. Manual mesh generation also falls into this explicit category. Here an explicit set of mesh elements is given to form an element mesh.

Both implicit and explicit element mesh generation can be broken up into yet smaller pieces. The function ToBoundaryMesh generates a boundary representation of an implicit or explicit input. This boundary representation can then in turn be given to ToElementMesh to form a full mesh. Among other uses, ToBoundaryMesh is useful if a numerical method only needs a boundary representation.

One important point to keep in mind is that regardless of which way the element mesh is created, the element mesh is, except in simple cases, only an approximation to the exact region. The exactness with which the element mesh captures essential parts of the region is crucial to the overall quality of the numerical solution.

Once a mesh is created, it can then be passed to numerical functions such as NDSolve.

### Passing an ElementMesh to NDSolve

As a first example, a Poisson partial differential equation (PDE) with Dirichlet boundary conditions is solved in a standard way. During this process, a mesh is internally generated. In the next step, that mesh is predefined and given as an argument to NDSolve.

Set up a region.
 In[2]:=
 Out[2]=
Set up a PDE operator.
 In[3]:=
 Out[3]=
Specify boundary conditions.
 In[4]:=
 Out[4]=
Solve the PDE.
 In[5]:=
 Out[5]=
Plot a contour plot of the solution with the element mesh from the interpolation function on top.
 In[6]:=
 Out[6]=

Note that the Interpolation function stores an ElementMesh if NDSolve made use of the finite element method. If an ElementMesh is stored with the interpolation function, then that can be extracted.

Extract the ElementMesh from an interpolating function.
 In[7]:=
 Out[7]=

Instead of specifying an implicit parametric region, it is also possible to specify an explicit ElementMesh. This can be done by using ToElementMesh.

Define an explicit mesh with four triangle elements.
 In[8]:=
 Out[8]=
Show a wireframe of the element mesh.
 In[9]:=
 Out[9]=

More information about the visualization of element meshes can be found in the element mesh visualization tutorial.

Next, the same PDE is solved, this time with only the explicit mesh defined.

Solve the PDE with an ElementMesh.
 In[10]:=
This makes a contour plot of the solution and plots the element mesh.
 In[11]:=
 Out[11]=

One should keep in mind that four elements are not sufficient in most cases to represent an accurate solution.

### Passing Options for the ElementMesh Creation to NDSolve

All options for ToElementMesh and ToBoundaryMesh can be given to NDSolve directly.

Solve the PDE with options given to influence the element mesh generation.
 In[12]:=

As an alternative, the element mesh can be generated prior to the simulation and given to NDSolve.

Generate an element mesh, visualize the mesh, and solve the PDE.
 In[13]:=
 Out[14]=
 In[15]:=
 Out[15]=

### Comparing ElementMesh and MeshRegion

Before a deeper discussion of the ElementMesh functionality is given, it is instructive to compare the ElementMesh object to the MeshRegion object.

The default "MeshOrder" for an ElementMesh is 2.

Investigate the mesh order of an ElementMesh.
 In[16]:=
 Out[16]=

The ability to deal with higher-order elements, expressed through the mesh order, has two distinct advantages:

• a higher-quality numerical approximation
• the ability to better approximate curved boundaries
Compare an analytical solution of a PDE with a numerical solution computed with a first-order mesh and a second-order mesh.
 In[17]:=
 Out[21]=
Discretize a Disk with DiscretizeRegion and inspect the Head.
 In[2]:=
 Out[3]=
Discretize a Disk with ToElementMesh.
 In[4]:=
 Out[4]=
Compute the area of an approximation of a Disk based on a MeshRegion and an ElementMesh.
 In[5]:=
 Out[5]=
 In[6]:=
 Out[6]=

The ElementMesh is able to approximate the Disk better because it uses a second-order approximation.

The conversion between MeshRegion and ElementMesh is easy.

Convert a MeshRegion to an ElementMesh.
 In[7]:=
 Out[7]=
Convert an ElementMesh to a MeshRegion.
 In[8]:=
 Out[8]=

Using a converted MeshRegion may not give expected results when the originating ElementMesh was of higher than first order, which is the default. One way to avoid that is to convert the ElementMesh to a first-order mesh and then convert to a MeshRegion.

Convert an ElementMesh to first order for a MeshRegion conversion.
 In[2]:=
 Out[3]=
Plot the MeshRegion and the ElementMesh.
 In[4]:=
 Out[4]=

In order to provide the advantages compared to the MeshRegion data structure, a few caveats are to be considered. In an ElementMesh, the difference between a boundary mesh and a full mesh is indicated by the presence or absence of full mesh elements. A boundary element mesh has Automatic set for the full mesh elements.

Create a boundary and a full ElementMesh.
 In[30]:=
 Out[30]=
 In[31]:=
 Out[31]=
Inspect the mesh elements of a boundary and a full mesh.
 In[32]:=
 Out[32]=
 In[33]:=
 Out[33]//Short=

A boundary ElementMesh does not need to be a closed curve.

Create a boundary ElementMesh that is not a closed curve.
 In[34]:=
 Out[34]=

This is needed for numerical algorithms (e.g. boundary integration) that do not need a full mesh. A not-closed boundary curve can, however, not be converted to a full element mesh. Note how that contrasts to a BoundaryMeshRegion: a BoundaryMeshRegion is always a representation of a full region by using the boundary to enclose that region.

A further difference between an ElementMesh and a MeshRegion is that a MeshRegion may contain lower-dimensional components that are detached from the full-dimensional mesh region elements.

Create a MeshRegion with a lower-dimensional component.
 In[35]:=
 Out[35]=
Inspect the dimensional components for a MeshRegion.
 In[36]:=
 Out[36]=
Convert and visualize a MeshRegion with lower-dimensional components to an ElementMesh.
 In[37]:=
 Out[37]=

Note that the lower-dimensional component was ignored during the conversion.

A boundary element mesh may have internal structure; for example, to represent two material regions.

Create and visualize a boundary ElementMesh with internal structure.
 In[38]:=
 Out[39]=
Create and visualize a full ElementMesh with an internal structure.
 In[40]:=
 Out[41]=

Note how the internal structure is still present in the final ElementMesh.

Following, for completeness, is an itinerary of the advantages and disadvantages to directly using an ElementMesh. Some of the remaining items will be further discussed in this tutorial.

Pros

• memory-efficient storage
• support for higher-order mesh elements
• support for curved mesh elements
• if needed, a conversion to e.g MeshRegion is easily possible
• works for both boundary and full meshes
• setting markers is easy
• influence the node ordering

Cons

• not in system context; a package needs to be loaded
• only usable within the finite element method framework

## Approximation of Regions with ElementMesh

The methods to create an ElementMesh are by using ToElementMesh for a full mesh or ToBoundaryMesh for a boundary mesh representation.

When ToElementMesh is called, ToBoundaryMesh is first called internally. While everything can be done with ToElementMesh, it can be convenient to inspect a boundary mesh before a full mesh is generated. ToBoundaryMesh is particularly useful when working with markers on the boundary.

### Manual Mesh Creation

A minimal ElementMesh is made up from coordinates and elements. The following elements are available:

An element is specified by its type, for example TriangleElement and a list of integer lists.

 In[42]:=
 Out[42]=

The integers are indices (also called incidents) that correspond to coordinates. In the preceding case, the TriangleElement contains two triangle elements, one made up of the incidents {1,2,3} and one made up of the incidents {3,4,1}.

To construct a mesh, coordinates must be given. The coordinates can be 1D, 2D or 3D but must match the element type. For a triangle mesh, 2D coordinates must be given.

 In[43]:=
 Out[43]=

In this example, the incidents of the second triangle element are {3,4,1} and refer to coordinates {1.,1.}, {1.,0.} and {0.,0.}, respectively.

Create an element mesh.
 In[44]:=
 Out[44]=

The concept of the element incidents is closely related to that of a GraphicsComplex.

Visualize the element mesh wireframe.
 In[45]:=
 Out[45]=

#### Line Meshes

For a 1D mesh, the mesh elements ei are LineElement. The boundary elements bi are then PointElement.

Create a line element mesh with three coordinates and two line elements.
 In[46]:=
 Out[46]=
Visualize the element mesh wireframe.
 In[47]:=
 Out[47]=

#### Triangle Meshes

For a 2D mesh, the mesh elements ei are TriangleElement or QuadElement. The boundary elements bi are then LineElement.

To create a triangle mesh, coordinates and triangle elements are needed. A linear triangle has three incidents and the element type is TriangleElement. The number of integers in an incident list determines the order of the mesh. In the triangle case, three incidents per element corresponds to linear triangles, which correspond to a first-order mesh. The incidents must be given in a counterclockwise manner.

Create a triangle element mesh with six triangle elements.
 In[16]:=
 Out[16]=
Inspect the mesh order.
 In[17]:=
 Out[17]=
Visualize the element mesh wireframe and the coordinates with their incident numbers.
 In[18]:=
 Out[18]=

The element-element connectivity provides neighboring information about elements.

Visualize the element mesh wireframe with the element's IDs in black and node IDs in red.
 In[19]:=
 Out[19]=

The first edge of the first element connects nodes {3,2} and does not have a neighbor element, and is thus 0. The second edge connecting nodes 2 to the center node connects to element 2. The third element has an edge connecting the center node to node 3; this edge is connected to element 6. All subsequent elements are treated in the same fashion.

Extract the element connectivity information.
 In[21]:=
 Out[21]=

The element containers, like TriangleElement, can also hold markers. These are convenient for marking different material domains. The number of markers must be the same as the number of elements.

Create a triangle element mesh with six triangle elements.
 In[9]:=
 Out[9]=
Visualize the element mesh wireframe with the element's markers in red.
 In[10]:=
 Out[10]=

Until now, the triangle meshes were of first order. A quadratic triangle mesh has six incidents per element. The additional coordinates are the mid-side node. Thus, a quadratic triangle element has six incidents. The first three are the linear incidents, and the following three are the second-order incidents. See TriangleElement.

Specify coordinates for a second-order mesh.
 In[53]:=
Specify six quadratic triangle elements without markers.
 In[54]:=
Create a second-order mesh.
 In[55]:=
 Out[55]=
Visualize the second-order mesh.
 In[56]:=
 Out[56]=

More information about the visualization of element meshes can be found in the element mesh visualization tutorial.

QuadElement meshes behave exactly the same as TriangleElement meshes, with the exception that for linear quad elements, four incidents per element are needed, and for quadratic elements, eight incidents per element are needed.

Construct coordinates on a circular perimeter.
 In[57]:=
The corresponding incidents.
 In[59]:=
Create a triangle element mesh.
 In[60]:=
 Out[60]=
Visualize the element mesh wireframe.
 In[61]:=
 Out[61]=

Markers can be given in exactly the same manner as in TriangleElement.

#### Mixed Element Type Meshes in 2D

For a 2D mesh, the mesh elements ei can be a combination of TriangleElement and QuadElement. The boundary elements bi are then LineElement.

Create a mixed-element mesh.
 In[62]:=
 In[63]:=
 In[65]:=
 Out[65]=
Visualize the element mesh wireframe.
 In[66]:=
 Out[66]=

All elements in a mixed-element mesh need to be of the same order; it is not possible to have first-order triangle elements and second-order quad elements in the same mesh.

Mixed-type element meshes can also hold markers.

Extract the element incidents from the previous elements and add integer markers.
 In[67]:=
 In[68]:=
 Out[68]=
 In[69]:=
 Out[69]=

The element connectivity keeps the information about marker boundaries. Whenever the marker value of two connecting elements is different, the element connectivity entry for that element is negative.

 In[70]:=
 Out[70]=

In the preceding graphic, the element number 2 with a marker 1 is connected to element number 4 with a marker 2. The element connectivity of this jump in marker values is stored in the negative sign.

Extract the element connectivity.
 In[71]:=
 Out[71]=

#### Boundary Meshes in 2D

Boundary meshes are useful to generate full meshes. In 2D, the boundary elements bi are the LineElement.

A boundary mesh with six coordinates and a bounding line.
 In[72]:=
 Out[72]=
Visualize the boundary mesh.
 In[73]:=
 Out[73]=
Convert the boundary mesh to a full mesh and visualize.
 In[74]:=
 Out[74]=
A boundary mesh with six coordinates, a bounding line and a separation.
 In[75]:=
 Out[75]=
Visualize the boundary mesh.
 In[76]:=
 Out[76]=
Convert the boundary mesh to a full mesh, respecting the separation and visualizing.
 In[77]:=
 Out[77]=

For a boundary mesh, you can add arbitrary points inside the bounding region to be part of the mesh.

Create boundary coordinates and some points placed on a circle.
 In[78]:=
Create the boundary mesh.
 In[79]:=
 Out[79]=
All coordinates given are referenced point elements.
 In[80]:=
 Out[80]=
Visualize the boundary mesh and the point elements.
 In[81]:=
 Out[81]=
Visualize the full mesh.
 In[82]:=
 Out[82]=

#### Tetrahedron Meshes

Three-dimensional manual mesh creation follows the same ideas as in one and two dimensions.

A linear tetrahedron element mesh with markers.
 In[83]:=
Visualizing the index of the coordinates at their respective positions.
 In[84]:=
 Out[84]=
Create the mesh.
 In[85]:=
 Out[85]=
Visualize the mesh with the elements' markers.
 In[86]:=
 Out[86]=

#### Hexahedron Meshes

Construct coordinates on a circular perimeter.
 In[87]:=
The linear incidents.
 In[89]:=
Create a hexahedron element mesh.
 In[90]:=
 Out[90]=
Visualize the boundary element mesh wireframe.
 In[91]:=
 Out[91]=

#### Mixed Element Type Meshes in 3D

For a 3D mesh, the mesh elements ei can be either a TetrahedronElement or HexahedronElement but not both.

#### Boundary Meshes in 3D

Boundary meshes are useful to generate full meshes. In 3D, the boundary elements bi are TriangleElement or QuadElement.

Here are coordinates in 3D space.
 In[92]:=
 Out[92]=
 In[93]:=
 Out[93]=
Create the boundary mesh.
 In[94]:=
 Out[94]=
 In[95]:=
 Out[95]=
Visualize the full mesh.
 In[96]:=
 Out[96]=

### Region Approximation Quality

For graphics primitives like Line or Polygon or a MeshRegion, a conversion to an ElementMesh is lossless. For example, an ElementMesh representation of a Rectangle is as exact or inexact, as the Rectangle itself represents a region. One way to estimate the quality of an approximation is to compare the area of the region in question, when possible.

Numerically integrate over a Rectangle.
 In[97]:=
 Out[97]=
Sum the area of an ElementMesh discretization of a Rectangle.
 In[98]:=
 Out[98]=

Compare this to a Disk, for example. No matter how finely the mesh is made and how high of a mesh order the elements are, the discretization will only be an approximation.

The difference of the exact value and the sum of the area of an ElementMesh discretization of a Disk.
 In[99]:=
 Out[99]=

The discrepancy is there, despite that the boundary points are close on the boundary.

Inspect the approximation quality of the boundary coordinates.
 In[100]:=
 Out[101]=
Inspect the influence the mesh order has on the approximation of a Disk.
 In[102]:=
 Out[102]=

In the case of a Disk, the mesh order plays a crucial role, since the ElementMesh can hold curved boundary mesh elements.

Inspect the influence the mesh granularity on the boundary has on the approximation of a Disk.
 In[103]:=
 Out[103]=

Also, the granularity of the boundary plays a role in how well a region can be approximated. The overall accuracy of the region conversion is controlled via the AccuracyGoal.

Specify an AccuracyGoal for a first-order approximation of a Disk.
 In[104]:=
 Out[104]=
Inspect the influence of an AccuracyGoal for a second-order approximation of a Disk.
 In[105]:=
 Out[105]=

Internally, ToBoundaryMesh is called first, and then the full mesh is created. This may introduce new nodes on the boundary. For a second-order mesh, the mid-side nodes are additionally inserted. Then a function to improve the position of these new boundary nodes is called.

Inspect the influence of "ImproveBoundaryPositions" for a second-order approximation of a Disk.
 In[106]:=
 Out[106]=

In this case, the result is not different from a first-order approximation.

For the creation of the boundary mesh, two boundary mesh generators are available. The first is based on RegionPlot and called "RegionPlot". This provides a fast boundary approximation. The default boundary mesh generator is called "Continuation" and based on a continuation method. This boundary mesh generator is somewhat slower, but high accuracy can be achieved.

Set up a region with cusps.
 In[4]:=
 Out[4]=
Use the "Continuation" boundary mesh generator and visualize the mesh.
 In[5]:=
 Out[6]=
Compare the area of the region Ω with the approximation.
 In[7]:=
 Out[7]=

As a contrast, compare the result to the fast region plot method.

Use the "RegionPlot" boundary mesh generator and visualize the mesh.
 In[8]:=
 Out[9]=

The visual inspection already shows that the cusps are not well resolved. The "RegionPlot" approximation may be improved by increasing the number of sample points (which is similar to PlotPoints).

Use the default boundary mesh generator with more sample points and visualize the mesh.
 In[10]:=
 Out[11]=
Compare the area of the region Ω with the approximation.
 In[12]:=
 Out[12]=

### Element Mesh Quality

Regardless of how well a region is approximated by an element mesh, the elements in the mesh themselves also exhibit an influence on the solution of a numerical task. For different numerical applications, different constraints on the element mesh come into play; in the finite element method, the following induce large discretization errors [4]:

• large angles (near 180°) can cause large interpolation errors
• small angles (near 0°) can cause the finite element stiffness matrix to be ill conditioned
• smaller elements offer more accuracy but cost more computational time
• small or skinny elements can induce instabilities in explicit time integration methods

The overall quality of a mesh can be expressed as a number between and , with being the best quality under a given quality estimate; indicates the worst quality. A negative quality indicates that the incidents of an element are not in the proper order, that the incidents produce a self-intersecting element, or both.

An ElementMesh has a notion of its quality. Once an ElementMesh is created, the quality of the mesh can be queried.

Construct a mesh and visualize a mesh.
 In[13]:=
 In[16]:=
 Out[16]=
 In[17]:=
 Out[17]=
Compute the quality of each element in an element mesh.
 In[18]:=
 Out[18]//Short=

The result of a "Quality" computation is a quality estimate for each mesh element grouped by mesh elements.

The mean and standard deviation of the element mesh quality can be computed.
 In[19]:=
 Out[19]=
Compute the minimum and maximum element mesh quality.
 In[20]:=
 Out[20]=
Visualize the mesh element quality in a histogram.
 In[21]:=
 Out[21]=

Second-order element meshes are transformed to first-order element meshes, and then the quality is computed.

A discussion of the specific quality estimates used for different mesh elements follows.

##### Line Element Mesh

For each line element, the mesh quality defaults to 1.

##### Triangle Element Mesh

The quality of a triangle element mesh is computed according to the following formula [1, 2]:

Here is the area of the triangle and is the edge length.

The optimal triangle element.
 In[125]:=
 Out[126]=

The quality of a quad element mesh is computed according to the following formula:

Here is the area of the quad and is the edge length.

 In[127]:=
 Out[128]=
##### Tetrahedron Element Mesh

The quality of a tetrahedron element mesh is computed according to the following formula [1, 3]:

Here is the volume of the tetrahedron and is implemented as , where is the edge length.

The optimal tetrahedron.
 In[129]:=
 Out[130]=
##### Hexahedron Element Mesh

The quality of a hexahedron element mesh is computed according to the following formula:

Here is the volume of the hexahedron and is the edge length.

The optimal hexahedron element.
 In[131]:=
 Out[132]=
##### References

[1] J. R. Shewchuk, "What Is a Good Linear Finite Element? Interpolation, Conditioning, Anisotropy, and Quality Measures (Preprint)," 2002, unpublished.

[2] R. P. Bhatia and K. L. Lawrence, "Two-Dimensional Finite Element Mesh Generation Based on Stripwise Automatic Triangulation," Computers and Structures, 36, 1990 pp. 309319.

[3] V. N. Parthasarathy, C. M. Graichen, and A. Hathaway, "Fast Evaluation & Improvement of Tetrahedral 3-D Grid Quality," 1991 (manuscript).

[4] S.-W. Cheng, T. K. Dey, and J. R. Shewchuk, Delaunay Mesh Generation, Boca Raton: CRC Press, 2013.

#### Visualize Low-Quality Elements

When a mesh is generated that has low-quality elements, it may become necessary to visualize those elements and then address the quality in that specific area.

Convert a space shuttle's orbiter to an element mesh.
 In[22]:=
 Out[23]=
Visualize the element mesh surface.
 In[24]:=
 Out[24]=
Compute the element mesh quality and overview quantities such as the minimum quality.
 In[25]:=
 Out[26]=
Visualize the mesh element quality distribution.
 In[27]:=
 Out[27]=

While the average quality of a mesh can be improved, it is possible that elements with a bad quality estimate are in corners of the geometry. Those cannot always be improved because the geometry dictates the shape. Nevertheless, it is important to be aware of them.

Improve the element mesh quality by requesting a smaller minimum edge ratio. This will result in more elements.
 In[28]:=
 Out[28]=
Compute quality data and overview quality quantities.
 In[29]:=
 Out[30]=

It can be noted that the overall average quality has improved. The mesh now, however, has more elements, which will result in a slightly longer computation time for a numerical analysis.

 In[31]:=
 Out[31]=
Visualize the boundary mesh.
 In[32]:=
 Out[32]=

To visualize the elements that are below a certain threshold, the poor-quality elements are selected from the mesh element quality list and visualized.

Visualize the mesh elements that have a quality of less than 0.1.
 In[33]:=
 Out[34]=
Visualize the mesh elements that have a quality of less than 0.1 combined with all mesh elements.
 In[35]:=
 Out[36]=

### Numerical Regions

The purpose of a NumericalRegion is to combine a symbolic region representation and boundary and full element mesh. This provides additional flexibility beyond the currently automated mesh generation. Here is an example: even though there is an option to control the maximum boundary cell size via the "MaxBoundaryCellMeasure" option for ToBoundaryMesh, it is not possible to refine only parts of the boundary. A refinement of the entire boundary, however, may lead to an unnecessary large number of mesh elements. One way to work around that is to manually generate the boundary mesh. Furthermore, if a symbolic description for the region is present, a high-quality second-order mesh with minimal elements can be generated.

Specify a symbolic region.
 In[2]:=
Generate a mesh.
 In[3]:=
 Out[3]=
Inspect the full mesh.
 In[4]:=
 Out[4]=

In this case, the mesh generation process failed to refine the small hole in the region center. While increasing the PrecisionGoal can help, it is not necessarily the best solution.

Use a higher PrecisionGoal to resolve the small feature.
 In[5]:=
 Out[5]=
Inspect the full mesh.
 In[6]:=
 Out[6]=

The number of mesh elements has increased significantly. One way to circumvent that is to combine the symbolic region description, manually generate a boundary mesh, and combine them in a NumericalRegion for final meshing. NumericalRegion is generated with ToNumericalRegion.

Generate a NumericalRegion from the symbolic region representation.
 In[7]:=
 Out[7]=

To manually generate the boundary mesh, the idea is to generate each part of the region separately and then combine them in a new boundary mesh.

Generate boundary meshes of the separate regions.
 In[8]:=
Extract the boundary elements from the boundary meshes.
 In[10]:=

The new boundary mesh is generated by joining the coordinates from both meshes and then constructing a new boundary elements list. The new boundary elements list is the combination of the boundary elements from one boundary mesh and an index-shifted version of the boundary elements from the second boundary mesh. The index shifting is necessary because the coordinates from the second mesh are now behind the coordinates from the first mesh.

Manually generate a boundary mesh.
 In[12]:=
Visualize the boundary mesh and a zoomed region of the boundary mesh.
 In[13]:=
 Out[13]=
Engage the numerical region with the new boundary mesh.
 In[14]:=
 Out[14]=
Inspect the symbolic region in the numerical region.
 In[15]:=
 Out[15]=
Inspect the boundary element mesh in the numerical region.
 In[16]:=
 Out[16]=
Generate the full mesh from the numerical region. Even though the boundary elements were first order, the elements can be made second order because the numerical region allows correct placement of the requisite mid-side nodes.
 In[17]:=
 Out[17]=

Note that there are far fewer mesh elements for the same approximation quality.

Inspect the wireframe mesh.
 In[18]:=
 Out[18]=
Verify that the mesh is second-order mesh.
 In[19]:=
 Out[19]=

## Element Meshes with Subregions

It is common for a PDE to interact with a region that is made up of multiple materials. The solution of PDEs will be of a higher quality if the mesh elements do not cross the internal boundaries. To illustrate this, a PDE with a variable diffusion coefficient is reconsidered and solved over two regions. (See: Solving Partial Differential Equations with the Finite Element Method.) One region respects the internal boundary, while the other does not.

Create and visualize a boundary element mesh with an internal boundary and without an internal boundary.
 In[148]:=
 Out[153]=

The diffusion coefficient has a jump discontinuity at .

Set up a diffusion coefficient that is space dependent.
 In[154]:=
 Out[154]=
Create and visualize the element meshes.
 In[155]:=
 Out[157]=
Specify a PDE operator and boundary conditions.
 In[158]:=
Solve the equation over each mesh.
 In[160]:=
 In[161]:=
Visualize the solution.
 In[162]:=
 Out[162]=
Visualize the difference between the two solutions.
 In[163]:=
 Out[163]=

The next example shows a circular region with a subregion and holes inside the subregion.

Set up the outer annulus and the inner region holes.
 In[37]:=
Display the region.
 In[41]:=
 Out[41]=

To easily create a mesh from the region that respects the interior boundary, the region is set up in such a way that all interior boundaries are created.

Specify the region as an implicit region and create an element mesh.
 In[42]:=
 Out[43]=

In the next step, what is a region hole and what is not is inverted in the subregion by explicitly specifying the region holes.

Create a mesh with specified region holes.
 In[44]:=
 Out[44]=

It is also possible then to refine, for example, one of the subregions.

Refine a subregion.
 In[45]:=
 Out[45]=

## Markers

Markers are positive integer numbers that are associated with the elements in a mesh. The main purpose of markers in meshes is to detach the (boundary) predicates from actual coordinates in the PDE specification. In other words, when a PDE is specified, it can be specified in such a manner that the PDE is independent of coordinates. This functionality is useful when the simulation region is subject to change but the PDE is not.

Create a triangle mesh with two element and markers.
 In[201]:=
 Out[201]=

In this case, the triangle element has two markers, one for each element.

Visualize the mesh and the markers.
 In[202]:=
 Out[202]=

To illustrate the usage of material markers, a PDE with a variable diffusion coefficient is reconsidered and solved (See: Solving Partial Differential Equations with the Finite Element Method).

Create and visualize a boundary element mesh with an internal boundary.
 In[2]:=
 Out[4]=

It is possible to specify regions markers with the "RegionMarker" option for ToElementMesh. For this, a coordinate within the region needs to be given, as well as an integer marker. Optionally, an additional maximum cell measure can be specified to refine a subregion.

Create and visualize an element mesh with internal markers.
 In[5]:=
 Out[6]=

Note that the lower part has a finer mesh than the upper part.

Extract the markers from the mesh elements with ElementMarkers.
 In[10]:=
 Out[10]=

The PDE coefficient can now be specified by accessing the ElementMarker in the predicate.

Specify the PDE coefficient with an ElementMarker.
 In[209]:=
 Out[209]=
Specify a PDE operator and boundary conditions.
 In[210]:=
Solve the equation.
 In[212]:=
Visualize the solution.
 In[213]:=
 Out[213]=

Typically, specifications for boundaries and subparts in an element mesh are given by some form of a predicate. As an alternative, the boundary mesh elements can also carry markers that can be used in the boundary condition specification.

Create and visualize a boundary element mesh with an internal boundary and boundary markers.
 In[11]:=
 Out[13]=
Create and visualize an element mesh with internal markers.
 In[14]:=
 Out[15]=
Visualize the boundary and its markers of the mesh.
 In[16]:=
 Out[16]=
Extract the markers from the boundary elements with ElementMarkers.
 In[17]:=
 Out[17]=
Extract the markers from the point elements with ElementMarkers.
 In[18]:=
 Out[18]=

The importance of the boundary and point elements is that these are where boundary conditions are applied when solving a PDE. Generalized Neumann boundary conditions are applied by integrating over the boundary elements. Dirichlet boundary conditions are applied at the point elements.

Note that the newly inserted points and segments have the correct boundary markers set.

Specify the PDE coefficient with an ElementMarker.
 In[222]:=
 Out[222]=
Specify a PDE operator.
 In[223]:=
 Out[223]=
Specify boundary conditions with markers.
 In[224]:=
Solve the equation.
 In[225]:=
 Out[225]=
Visualize the solution.
 In[226]:=
 Out[226]=

Note that now the PDE coefficient and boundary conditions are independent of coordinates and a new geometry can readily be put in place without the need to modify the PDE or boundary conditions.

To summarize: a set of elements is given in the form eltype[incidents,markers]. incidents is a list of the list of coordinate identities for each element. markers is a list of the same length as incidents and can be used to identify different parts of the domain or boundary where some material property might be different or a different boundary condition might apply. In evaluating on a given element, ElementMarker will effectively be replaced by the marker for that element.

Markers may be present in the "MeshElements", "BoundaryElements" and "PointElements" groups of elements. In each group, markers serve a different purpose: Markers in the "MeshElements" group of elements can be used in the PDE coefficients. Markers in the "BoundaryElements" group of elements can be used by NeumannValue or PeriodicBoundaryCondition, and markers in the "PointElements" group of elements can be used by DirichletCondition.

Geometries may be complex. In this case, it is not always easy to identify parts of the element mesh by predicates.

Create a list of boundaries and visualize them.
 In[2]:=
 Out[3]=
Create a boundary mesh by setting the boundaries smaller than 0 and combine them with And.
 In[4]:=
 Out[4]=
Visualize the boundary mesh.
 In[5]:=
 Out[5]=

By default, during boundary mesh generation an automatic grouping of contiguous boundaries is computed. The automatic grouping works by inspecting boundary normals and comparing them to each other. If the absolute value of the dot product of two normal vectors is above a threshold (i.e. the vectors have close to the same direction), then the neighboring segments are considered contiguous.

Inspect the boundary element marker union for a given mesh.
 In[6]:=
 Out[6]=
Generate a list of colors for the grouping.
 In[7]:=
 Out[8]=
Visualize the mesh with the colors corresponding to the contiguous boundary groups.
 In[9]:=
 Out[9]=
Get the boundary normals and scale them to visualize them with the mesh wireframe.
 In[10]:=
 Out[12]=

During the generation of the full mesh, these boundary markers will then be propagated and can later be used from within NDSolve as described above.

It is possible to write functions that allow for the placing of markers in boundary meshes. Two functions for boundary marker placement are available. One operates on boundary points, and the other operates on boundary lines in 2D and boundary faces in 3D.

Write a function that given coordinates of the boundary mesh, will return integer markers if the coordinates satisfy a predicate.
 In[13]:=
Apply the point marker function to the coordinates of the boundary mesh.
 In[14]:=
 Out[14]=
Visualize the integer markers attributed to the coordinates of the boundary mesh.
 In[15]:=
 Out[15]=

Note that the order of the Which statement preceding matters. If a coordinate is on several of the boundaries, the first predicate that matches is returned.

A second function can be written to act on the boundary edges. This function gets the coordinates of the boundary element and the already-computed markers of the point function.

Here is a function that computes integer markers for edges depending only on the integer markers of the boundary points.
 In[16]:=
The point and edge marker functions can be given to ToBoundaryMesh.
 In[17]:=
 Out[17]=
Inspecting the boundary elements of the mesh reveals the boundary markers.
 In[18]:=
 Out[18]=
Visualize the boundary mesh with its markers.
 In[19]:=
 Out[19]=
Inspecting the point elements of the mesh reveals the point markers.
 In[20]:=
 Out[20]=
Visualize the boundary mesh with its markers.
 In[21]:=
 Out[21]=
Convert the boundary mesh to a full mesh.
 In[22]:=
 Out[22]=
Inspect the union of the point markers.
 In[23]:=
 Out[23]=
Visualize the element mesh and the boundary markers.
 In[24]:=
 Out[24]=
Inspect the union of the point markers.
 In[25]:=
 Out[25]=

The union of the point markers indicates how many mesh element style directives need to be given.

Visualize the element mesh and the point markers.
 In[26]:=
 Out[26]=

Note that the marker values at the edges and points have been propagated after the full mesh was generated.

As an alternative, a full mesh can be generated directly.

Directly create a full mesh with point and boundary markers.
 In[27]:=
 Out[27]=

## Element Meshes in Other Functions

### Region Membership Tests

Given a point, you can test whether the point is in a region using RegionMember.

Create a region and test if the point is in the region .
 In[173]:=
 Out[174]=

Once a region is specified, for it to be used by the finite element method, it needs to be subdivided or meshed into elements that approximately cover the region. If a mesh is already available, ElementMeshRegionMember can be used.

Create a mesh and test if the point is in the mesh.
 In[175]:=
 Out[176]=

Test if a set of points is or is not within a meshed region.

Test if a number of points are inside a meshed region.
 In[177]:=
 Out[181]=

For points that are close to the boundary of the region, wrong results are possible. This is the case when even a second-order approximation is not good enough to represent the continuous boundary properly.

Test a large number of points for region inclusion and extract those that differ from the inclusion of the exact region.
 In[182]:=
 Out[185]=
 Out[187]=
Visualize the mesh with the points close to the boundary.
 In[188]:=
 Out[188]=

 In[189]:=
 Out[189]=
 In[190]:=
 Out[190]=
 In[191]:=
 Out[192]=
 Out[194]=

### Interpolation

When NDSolve computes a solution of a PDE via the finite element method, the returned InterpolatingFunction contains an element mesh.

Solve a PDE.
 In[195]:=
This gets the ElementMesh from the InterpolatingFunction returned for the Poisson equation.
 In[196]:=
 Out[196]=

It is also possible to construct an InterpolatingFunction from an ElementMesh.

Create an ElementMesh.
 In[197]:=
 Out[197]=
Evaluate a function over the coordinates of the mesh.
 In[198]:=
 In[199]:=
 Out[199]=
Visualize the InterpolatingFunction.
 In[200]:=
 Out[200]=