Tutorial¶
This page describes how to setup and run the MeshGenC++ mesh generator for a particular 2D example. If you encounter any difficulties, please send e-mail to the discussion group.
Example details¶
In this example we will use MeshGenC++ to generate a mesh for the domain that is made of up of the intersection of the interior of a square and the exterior of two circles and two ellipses (see images below).


In order to generate such a mesh we will need three essential pieces:
- An input file that contains basic information about the mesh we wish to generate.
- A function that returns the signed distance from any point to the boundary of the domain (in reality we only need an approximate signed distance function -- i.e., a properly normalized level set function).
- A function that returns at every point in the domain a desired grid spacing value.
In the description below we go step-by-step through the process of generating the mesh.
Setup¶
First we will need to create a directory to house our example. Do this as follows:
$ cd $MESHGENCPP/apps/2d
$ mkdir myexample
$ cd myexample
Makefile¶
Next we need to create a Makefile (the name of this file is
Makefile
).
The basic MeshGenC++ makefile is of the following form:
#
# MeshGenC++ Makefile
# To make an executable, type: make
# (from the application sub-directory)
### definitions ###
# default/library definitions
include $(MESHGENCPP)/lib/2d/Makefile.defs
# compiler options
#FFLAGS = -c -O4
#LFLAGS =
#LINK = g++
# overridden library objects
#
#MeshPreProcess = MeshPreProcess
#MeshPostProcess1 = MeshPostProcess1
#MeshPostProcess2 = MeshPostProcess2
# place to add object modules
#
#ALL_OBJECTS = $(COMMON_OBJECTS)
#ALL_SOURCES = $(COMMON_SOURCES)
### targets ###
.cpp.o: ; $(LINK) $(FFLAGS) $*.cpp -o $*.o
mesh.exe: $(ALL_OBJECTS)
$(LINK) $(LFLAGS) $(ALL_OBJECTS) -o mesh.exe
include $(MESHGENCPP)/lib/2d/Makefile.targets
### DO NOT remove this line - make depends on it ###
main.cpp¶
Next we need to create the file main.cpp
. The basic MeshGenC++ main.cpp
file is of the following form:
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include "meshdefs.h"
// ==============================================================================
//
// Copyright J.A. Rossmanith and the DoGPack Team
//
// This software is made available for research and instructional use only.
// You may copy and use this software without charge for these non-commercial
// purposes, provided that the copyright notice and associated text is
// reproduced on all copies. For all other uses (including distribution of
// modified versions), please contact the author at the address given below.
//
// *** This software is made available "as is" without any assurance that it
// *** will work for your purposes. The software may in fact have defects, so
// *** use the software at your own risk.
//
// ==============================================================================
int main(int argc, char* argv[])
{
//
// NOTE: You should not have to modify this part of the code.
// To change parameters, modify the following files:
// 1. input2D.data
// 2. SignedDistance.cpp
// 3. GridSpacing.cpp
//
// Get current time
double time1 = time(NULL);
// Call the mesh generator
int meshgen2D(int argc,char**argv);
int m = meshgen2D(argc, argv);
// Get current time
double time2 = time(NULL);
// Output elapsed time
cout << setprecision(5);
cout << " Total elapsed time in seconds = " << setw(11)
<< scientific << time2-time1 << endl << endl;
return m;
}
input.data¶
Next we need to create and edit the input file (input.data
).
In particular, we need specify the following pieces of
information:
- Initial grid spacing (
H0
): this will control the initial spacing of triangles. The number of elements that are created in this initial triangulation is the maximum number of elements during the entire mesh generation process. - Bounding box (
xmin
,xmax
,ymin
,ymax
): a box that encloses the entire region that will be triangulated. - Number of fixed points: sets the number of points that will never get deleted or moved during the mesh generation process.
- Fixed points (
x
,y
): List of x and y coordinates of all the points that will never get deleted or moved during the mesh generation process.
The final input.data
will be of the following form:
Unstructured : Grid type (Structured vs. Unstructured)
0.02 : Initial grid spacing (H0)
50000 : Maximum allowed iterations
----------------------------------------------------------------
Bounding box:
-1.0e0 : xmin
1.0e0 : xmax
-1.0e0 : ymin
1.0e0 : ymax
----------------------------------------------------------------
4 : Number of fixed points
----------------------------------------------------------------
Fixed points (x y):
-1.000000000000000e+00 -1.000000000000000e+00
-1.000000000000000e+00 1.000000000000000e+00
1.000000000000000e+00 -1.000000000000000e+00
1.000000000000000e+00 1.000000000000000e+00
SignedDistance.cpp¶
Next we will need to create a signed distance function to the boundary of the domain that we wish to mesh. This function takes as input a point and returns one the following three possibilities:
- If the point is interior to the domain, the signed distance function returns -1 times the distance to the closest point on the domain boundary.
- If the point is exterior to the domain, the signed distance function returns the distance to the closest point on the domain boundary.
- If the point is on the domain boundary, the signed distance function returns zero.
In practice it is generally quite difficult to create a mathematically rigorous signed distance function for a particular domain. For the purposes of the mesh generator, we only really need a level set function that is approximately a signed distance function. This is because the only place in the MeshGenC++ code that makes use of the distance part of the signed distance function is in the projection of points from the exterior of the domain back onto the domain boundary -- this projection is typically done on points that are already very close to the boundary.
For the current example, we use the following level set function. It is not a rigorous signed distance function, but it is easy to create, and works very well in practice.
#include "meshdefs.h"
// Signed distance function:
//
// SignedDistance(x,y) < 0 inside the region
// SignedDistance(x,y) = 0 on the boundary
// SignedDistance(x,y) > 0 outside of the region
//
double SignedDistance(point pt)
{
double Min(double,double);
double x = pt.x;
double y = pt.y;
double out1 = (x+1.0);
double out2 = -(x-1.0);
double out3 = (y+1.0);
double out4 = -(y-1.0);
double lft_eye = sqrt(pow(x+0.5,2) + pow(y-0.5,2)) - 0.25;
double rgt_eye = sqrt(pow(x-0.5,2) + pow(y-0.5,2)) - 0.25;
double mouth = sqrt(pow(x,2) + 10.0*pow(y+0.5,2)) - 0.75;
double nose = sqrt(3.0*pow(x,2) + pow(y-0.1,2)) - 0.15;
double dist = -Min(Min(Min(Min(out1,out2),
Min(out3,out4)),
Min(lft_eye,rgt_eye)),
Min(mouth,nose));
return dist;
}
GridSpacing.cpp¶
The function GridSpacing.cpp
controls the relative spacing of elements in the
mesh. If this function returns a constant, then the mesh generator
will attempt to create a mesh with spacing that is roughly uniform.
In this example, we will pick a spacing that concentrates more points
near the boundaries and less in the interior regions. We can use the
already existing SignedDistance.cpp
function to help us out.
In particular, we use the following file:
#include "meshdefs.h"
// Grid spacing function:
//
// This functions sets a relative grid spacing of points
//
// The input is a point (i.e., x and y coordinate), and the
// output is a real positive number called "hdist". Large (small)
// "hdist" means relatively large (small) grid spacing (relative to
// the maximum and minimum values of GridSpacing.cpp).
//
// For example, GridSpacing = 1 for all input x and y and
// GridSpacing = 55 for all input x and y
//
// will produce the same nearly uniform mesh since
// the relative variation of GridSpacing in both
// examples is zero.
//
double GridSpacing(point pt)
{
double Min(double,double);
double xin = pt.x;
double yin = pt.y;
double SignedDistance(point pt);
double dist = SignedDistance(pt);
double hdist = 0.2e0 - dist;
return hdist;
}
Compilation/Execution¶
In order to compile this example simply type:
$ make
Once compiled, execute the code by typing:
$ mesh.exe
During the running of the program you will see printed to the screen the iteration count, as well as statements that show whenever a new triangulation is computed. After successful completion of the code, a statement similar to the following is produced:
SUMMARY OF RESULTS:
-------------------
Number of Elements: 8206
Number of Physical Elements: 7455
Number of Ghost Elements: 751
Number of Nodes: 4851
Number of Physical Nodes: 4100
Number of Boundary Nodes: 751
Number of Edges: 11558
Total Area Covered: 3.0071970517733870e+00
Area Ratio: small/large: 7.8272678749387078e-02
Angle Ratio: minAngle/60: 5.8289165748986904e-01
Total elapsed time in seconds = 1.50000e+01
Vizualization¶
If MATLAB is installed, the resulting mesh can be visualized by executing the following script within a MATLAB command window:
>> plotmesh2
Note
Before executing this command, first open MATLAB, then change
directory to the $MESHGENCPP/apps/2d/myexample
directory in the
MATLAB command window.
This should result in the following two plots being produced:


Otherwise, if matplotlib is installed, the resulting mesh can be visualized by executing the following python script:
$ python $MESHGENCPP/viz/python/plotmesh2.py
or using the following shortcut (this shortcut is defined in
setenv.bash
and setenv.csh
files):
$ plotmesh2
This should result in the following two plots being produced:

