# 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;
}

## 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:

Once compiled, execute the code by typing:

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:

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):

This should result in the following two plots being produced: