Triangle Mesh Generator GUI and CLI Integration with FEATool

Banner - Triangle Mesh Generator GUI and CLI Integration with FEATool

FEATool-Triangle Mesh Generator Integration

The fast and efficient 2D mesh and grid generator, Triangle, by J.R. Shewchuk’s is fully integrated with FEATool Multiphysics [1][2][3]. Both MATLAB command line interface (CLI) usage is supported with the gridgen function, as well as FEATool GUI usage by selecting the Triangle in the Grid Generation Settings dialog box.

Advantages of using Triangle compared to the built-in grid generation function is firstly the overall speed, as it is one of the fastest 2D unstructured mesh generators available (completely written in C code). Moreover, Triangle features better support for specifying the grid size in different subdomains and geometry regions, as well as on boundaries, allowing for greater flexibility and higher quality grids adapted to specific problems and geometries.

MATLAB Grid and Mesh Generation with Triangle and the FEATool GUI

To evaluate the performance of Triangle and compare it to the built-in grid generator a simple benchmark test case was employed. The test case consisted of generating a uniform mesh for a unit circle with average grid sizes hmax = [0.1 0.05 0.025 0.0125 0.00625]. The normalized timings for using gridgen with the default algorithm

geom.objects = { gobj_circle() };
grid = gridgen( geom, 'hmax', hmax );
t = toc

The time to mesh a unit circle in MATLAB and Octave with DistMesh, as well as with Triangle is shown in the figure below.

MATLAB, Octave, and Triangle Grid Generation Benchmark and Comparison

From the results one can see that for the finest grid (hmax = 0.00625, consisting of approximately 185000 triangles) required 10 seconds for Triangle, 1 minute for DistMesh and MATLAB, and close to 7 minutes for DistMesh and Octave (suffering from lack of Just-In-Time JIT compilation). Also note that the Triangle timings also includes time taken for IO export and import, that is the total time the user might typically see. Triangle can clearly offer magnitudes of speed improvements for basic two-dimensional unstructured grid generation.


First please ensure that the latest version of FEATool Multiphysics is installed. If Triangle is selected as grid generation algorithm but not found, FEATool will automatically try to download, (compile), and install the mesh generator binary into the userpath/.featool folder.

Should the Triangle installation or compilation fail, please manually download, compile, and install Triangle from the original source reference [1].

GUI Usage

Once installed, the Grid Generation Settings dialog box will feature a Triangle selection option from the Grid Generation Algorithm drop-down box. Moreover, the following options also apply to the Triangle mesh generation algorithm

  • The Subdomain Grid Size, hmax, indicates the target grid cell diameter, and can either be a single scalar prescribing the grid size for the entire geometry, or a space separated string of numbers (array) where the hmax values correspond to the generated subdomains.

  • Boundary Grid Size, hmaxb, is analogous to hmax but related to boundaries (edges). hmaxb can consist of a single scalar applicable to all boundaries, for example


    prescribing a mean cell edge length of 0.1 on every boundary. hmaxb can also be a numeric array with entries corresponding to individual boundaries, for example

    [ 0.1  0.2  0.3  0.4 ]

    specifying cell edge length 0.1 for boundary 1, 0.2 for boundary 2 etc. Lastly, hmaxb can also be given as a cell array where each entry and boundary can be prescribed a single value for the mean cell edge size or a numeric array of grid point distributions (spanning 0 to 1) along the boundary. For example

    { 0.1  [0 0.1 0.5 1]  0.3  [1 0.8 0.2 0] }

    where here boundaries 1 and 3 are prescribed mean edge lengths 0.1 and 0.3, respectively. Boundary 2 is assigned nodes at parametrized positions 0, 0.1, 0.5, and 1 while boundary 4 the nodes are assigned in reverse.

  • The Quality slider (which corresponds to theTriangle q parameter, default 28 degrees) sets a minimum target angle (values less than 33 are generally acceptable, while higher values might prevent Triangle convergence).

  • The Smoothing parameter specifies the number of post grid smoothing steps to perform (default 3).

The Generate grid button effectively calls the gridgen function from the GUI with the ‘gridgen’ ‘triangle’ property/value pair as input arguments, which in turn makes a system call to the Triangle binary, after which the new grid is automatically imported and displayed.

CLI Usage

On the MATLAB command line the gridgen function is used to call Triangle to generate an unstructured 2D triangular grid. The following syntax is used

grid = gridgen( SIN, VARARGIN, 'gridgen', 'triangle' )

where SIN is a valid FEATool fea problem struct or cell array of geometry objects. gridgen also accepts the following property/value pairs (VARARGIN).

Property    Value/{Default}            Description
hmax        scal/arr {0.1}             Target grid size for geometry/subdomains
hmaxb       scal/arr {[]}              Target grid size for boundary edges
q           scalar   {28}              Minimum target angle (quality)
nsm         scalar   {3}               Number of (post) grid smoothing steps
intb        logical  {false}           Keep internal boundaries
syscmd      string   {'default'}       Triangle system call command (default
                                       'triangle -I -q%f -j -e -a -A %s.poly')
compcmd     string   {'default'}       Triangle unix/linux compilation command
                                       ('cc -O triangle.c -lm -o triangle')
fname       string   {'fea_tri_UID'}   Triangle imp/exp file name (root)
fdir        string   {tempdir}         Directory to write help files
clean       boolean  {true}            Delete (clean) Triangle help files
instdir     string   {userpath/.featool}  Triangle installation directory

As also discussed above, among the properties hmax indicates target grid cell diameters, and is either a numeric scalar valid for the entire geometry or an array with hmax values corresponding to the subdomains. hmaxb is similar to hmax but a numeric array with a hmaxb values corresponding to the boundaries (including internal boundaries). q (default 28 degrees) specifies a minimum target grid size (values less than 33 are generally acceptable, while higher values might prevent convergence). nsm (default 0) the number of gridsmooth smoothing steps to perform. More detailed information regarding the mesh generation options can be found in the documentation for Triangle [1].

For more information about CLI usage access the function help by entering

>> help gridgen

Grid Generation Examples

MATLAB Mesh Generation Triangle Grid Examples
  1. Unit square with uniform global grid size set to 0.1

    grid = gridgen( {gobj_rectangle()}, 'hmax', 0.1, 'gridgen', 'triangle' );
    plotgrid( grid )
  2. Unit square with fine grid along the top boundary.

    grid = gridgen( {gobj_rectangle()}, 'hmax', 0.5, ...
                         'hmaxb', [0.5 0.5 0.01 0.5], 'gridgen', 'triangle' );
    plotgrid( grid )
  3. Domain with fine grid along curved boundaries (number 5 and 6)

    geom.objects = {gobj_rectangle() gobj_circle([0 0],.6) gobj_circle([1 1],.3,'C2')};
    geom = geom_apply_formula( geom, 'R1-C1-C2' );
    grid = gridgen( geom, 'hmax', .1, 'hmaxb', [.1 .1 .1 .1 .01 .01], ...
                    'gridgen', 'triangle' );
    plotgrid( grid )
  4. Two connected subdomains with refined grid along the shared boundary (9)

    geom.objects = { gobj_rectangle(-2e-3,0,-8e-3,8e-3), ...
                     gobj_polygon([0 -6e-3;2e-3 -5e-3;2e-3 4e-3;0 6e-3]) };
    hmax  = 5e-4;
    hmaxb = hmax*ones(1,9);
    hmaxb(9) = hmax/5;
    grid  = gridgen( geom, 'hmax', hmax, 'hmaxb', hmaxb, 'gridgen', 'triangle' );
    plotgrid( grid )
  5. Component with fine grid on subdomains 2 and 3, and curved boundaries

    r1 = gobj_rectangle( 0, 0.11, 0, 0.12,  'R1' );
    c1 = gobj_circle( [ 0.065 0 ],   0.015, 'C1' );
    c2 = gobj_circle( [ 0.11 0.12 ], 0.035, 'C2' );
    c3 = gobj_circle( [ 0 0.06 ],    0.025, 'C3' );
    r2 = gobj_rectangle( 0.065, 0.16, 0.05, 0.07, 'R2' );
    c4 = gobj_circle( [ 0.065 0.06 ], 0.01, 'C4' );
    geom.objects = { r1 c1 c2 c3 r2 c4 };
    geom = geom_apply_formula( geom, 'R1-C1-C2-C3' );
    geom = geom_apply_formula( geom, 'R2+C4' );
    hmax  = [0.0015 0.02 0.0015];
    hmaxb = 0.02*ones(1,34);
    hmaxb([8:12]) = 0.0025;
    grid  = gridgen( geom, 'hmax', hmax, 'hmaxb', hmaxb, 'gridgen', 'triangle' );
    plotgrid( grid )
  6. Complex geometry with several holes and subdomains

    w = 10e-4; L = 3*w; H = 5*w;
    p1  = gobj_polygon( [w/10 0;L 0;L H-H/3;L H;0 H;0 H/3], 'P1' );
    r1  = gobj_rectangle( (L-w/4)/2, (L+w/4)/2, -sqrt(eps), H, 'R1' );
    c1  = gobj_circle( [2*w/3 3*w], w/3, 'C1' );
    c2  = gobj_circle( [2*w/3 2*w], w/3, 'C2' );
    c3  = gobj_circle( [2*w/3 1*w], w/3, 'C3' );
    c4  = gobj_circle( [L-w/2 4.5*w], w/8, 'C4' );
    c5  = gobj_circle( [L-w   4.5*w], w/8, 'C5' );
    c6  = gobj_circle( [L-w/2 4*w], w/8, 'C6' );
    c7  = gobj_circle( [L-w   4*w], w/8, 'C7' );
    c8  = gobj_circle( [L-w/2 3.5*w], w/8, 'C8' );
    c9  = gobj_circle( [L-w   3.5*w], w/8, 'C9' );
    c10 = gobj_circle( [L-w/2 3*w], w/8, 'C10' );
    c11 = gobj_circle( [L-w   3*w], w/8, 'C11' );
    geom.objects = { p1 r1 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 };
    geom = geom_apply_formula( geom, 'P1-C1-C2-C3-C4-C5-C6-C7-C8-C9-C10-C11' );
    hmaxb = w/5*ones(1,59);
    hmaxb([5 9]) = w/50;
    grid  = gridgen_triangle( geom, 'hmax', w./[5 20 5], 'hmaxb', hmaxb, 'gridgen', 'triangle' );
    plotgrid( grid )

Usage Notes

For geometries with multiple and overlapping geometry objects the actual subdomain numbering will generally not correspond to the geometry object numbering (two intersecting geometry objects will for example create three or more subdomains and several internal boundaries). In this case the actual subdomain and boundary numbering for vector valued hmax and hmaxb arrays can easiest be visualized and determined by first creating a coarse grid and switching to Equation/Subdomain and Boundary modes, respectively.

Furthermore, in contrast to the standard gridgen function, _gridgentriangle can identify and include internal boundaries (with the intb flag on). These internal boundaries can also be subject to boundary conditions, or alternatively should be assigned neutral/symmetry (homogeneous zero Neumann) boundary conditions if they are to be considered non-active boundaries (acting as if they were not present and ignored).

The temporary Triangle generated poly and tri data files can be found in the specified fdir directory (default given by the MATLAB tempdir function).

Lastly, even if a specific boundary node distribution has been prescribed through the cell array hmaxb parameter, Triangle may insert additional nodes if necessary in order to achieve and acceptable grid quality (depending on the prescribed q parameter).


[1] The Triangle Mesh Generator home page (

[2] J.R. Shewchuk, Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator, in Applied Computational Geometry: Towards Geometric Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of Lecture Notes in Computer Science, pages 203-222, Springer-Verlag, Berlin, May 1996. (From the First ACM Workshop on Applied Computational Geometry).

[3] J.R. Shewchuk, Delaunay Refinement Algorithms for Triangular Mesh Generation, Computational Geometry: Theory and Applications 22(1-3):21-74, May 2002.

Category: grid

Tags: external triangle


Twitter LinkedIn Facebook