Skip to content

Preprocessing

The preprocessing step is not specific to the CFD workflow on HPC. In fact, many of these steps, such as geometry generation, mesh creation, and input file setup, are integral steps to any CFD simulation. Out of completeness, we present the main steps, as well as specific considerations for preprocessing when using HPC.

HPCcompromise.

Preprocessing main steps, concepts, and toolsets

The steps for preprocessing CFD simulations are very broadly divided into:

  1. Construction of the geometry;
  2. Discretization of the fluid domain;
  3. Setup the simulation.

These steps are broken down in the following subsection, but first, we briefly discuss the particularities of the preprocessing workflow on HPC systems.

preprocessing workflow

For small non-HPC simulations, where memory or computational limitations are not an issue, the preprocessing, processing, and postprocessing steps can be done locally. With larger CFD simulations, this workflow needs to be revisited. Two main types of workflow emerge for the preprocessing step:

  1. Local preprocessing
  2. Remote preprocessing

The optimal workflow for a given problem depends on a number of factors including local workstation computational resources, toolset, and, even, the internet bandwidth. But the most significant constraint lies in the local workstation memory during the meshing stage. Complex mesh generation is often a memory intensive process that may constrain the user to rely on remote preprocessing on HPC systems. Let us explore these ideas in more detail.

CFD Example.

Comparison of local and remote preprocessing workflow.

Local preprocessing

For smaller CFD problems or simple meshing needs, local preprocessing is usually the preferred approach. Here, the user is on a local workstation and can generate the geometry and the mesh. Then using copying techniques seen in the first section can copy the resulting mesh to the remote HPC system for processing the simulation. This is usually the standard workflow for most users.

Remote preprocessing

When the CFD problem is larger or the mesh is very complex, the limitations of the workstation constrain the user to resort to remote preprocessing. In this case, the preprocessing toolset is run on the remote HPC system, either interactively or headless (without gui). This allows the user to use the larger computational and memory resources of the remote system for preprocessing. As the mesh is generated on the same HPC system where the CFD simulation will be run, there is the added benefit of maintaining the data at the same location. Now, it is also possible to use a hybrid approach where, for example, the Computer-aided Design (CAD) is done locally and transferred to the remote system for the meshing phase. When considering remote preprocessing, it is important to take into account:

  • availability of the preprocessing tools on remote system,
  • licence constraints for commercial software,
  • speed/lag time to run the software remotely.

Toolsets

Many tools are available to complete the preprocessing step. Here, we provide a brief overview of some of the tools available. Please keep in mind that some CFD solvers, especially commercial tools, have geometry and meshing capabilities built in.

Open-source options:

  • Gmsh: most versatile open-source meshing tool for CFD applications for structured and unstructured grids
  • FreeCAD: tool to generate CAD definition of the CFD domain, must be combined with a mesher to generate a CFD mesh
  • Salome: SMESH within this platform is a full fledge meshing tool that can accommodate complex geometries
  • blockMesh: a utility within the openFoam framework to generate structured mesh
  • snappyHexMesh: a utility within the openFoam framework to generate an unstructured mesh around an arbitrarily complex CAD geometry
  • meshio: although it is formally not a meshing tool, this software can translate mesh files among many different mesh formats

Commercial tools

For this course, we focus on Gmsh, which is a highly versatile open-source mesher that can create a structured or unstructured grid. It can also output natively or near-natively in a number of well-known meshing formats. A Gmsh tutorial can be found here. For users that do not have access to the Digital Research Alliance of Canada systems or that want to install the programs locally, please consult the overview page for links to the software.

Construct the geometry

For complex geometries, for example pumps, industrial applications, or HVAC fluid dynamics, the geometry of the simulation domain should be generated in a dedicated CAD software. Many meshing tools have limited capabilities to build complex geometries; for very simple geometries, the features of the meshing software may be sufficient. If the CAD can be natively developed within the meshing software, it should be favoured as it facilitates the integration of the geometry and mesh and enables an easier parametrization. Although some commercial tools have seamless integration between the CAD and meshing software, most meshing tools require an additional step to generate and transfer the CAD geometry. It should be noted that while some CAD software have meshing capabilities, they usually cater to solid mechanics community, which has very different types of constraints on their mesh generation.

The format of the CAD geometry depends on the compatibility with the meshing software. Typically, IGES or STEP formats are widely used in meshing software. For some meshing applications (such as snappyHexMesh) where only the outer hull of the geometry is needed, a fluid mesh can be generated from an STL (Stereolithography) file.

Example: Cylinder in crossflow (domain generation)

For this example, we construct a domain and mesh to simulate a cylinder in crossflow. For this purpose, we will use Gmsh. Gmsh is an widely used open-source meshing tool and is installed on the Digital Research Alliance clusters but you can also download it locally. We will not cover the usage of Gmsh in much detail and the interested reader can consult the tutorial online to supplement the knowledge provided here. Gmsh can be used either through its GUI (graphical user interface) or with an interpreted script. Note that when using the GUI, Gmsh automatically writes the script. Therefore, by saving and modifying the script, you can reproduce a mesh without a GUI. Furthermore, with a very large mesh, you can define the mesh locally (in the script) and run it remotely. For this example, we will directly work in the Gmsh script.

HPCcompromise.

Gmsh interface and location of the script.

Let us assume that we have computed all the necessary domain size in a previous step and we have a general idea of the geometry we hope to create: HPCcompromise.

Example of geometry we want to create.
As we have a non-slip wall at the cylinder, we know that we need to pay close attention to the mesh at this location, so we create a zone around the cylinder which will have a higher mesh density. Now, we can parameterize these values into the Gmsh script below. In Gmsh, we must also, at this stage, make a decision on the mesh density (highlighted in the example). Note that the raw input file can be downloaded from the Git repository of the course.

gmsh_cylinder.geo
SetFactory("OpenCASCADE");
upstream = 200; // upstream distance from cylinder
downstream = 500; // downstream distance from cylinder
height = 100; // height from cylinder
width = 50; // width of computational domain
radius =10; // radius of cylinder
dx = 0.25; // size of mesh near cylinder
BL = 1.2; // Approximate boundary layer thickness
dxfar = 10.0; // size of mesh far field
nBL = 11; // grid points in BL
nCirc = 25; // grids in circumference
nZ = 5; // grid points in the z-direction
// Generate domain point-by-point
Point(1) = { 0, 0, 0, dx};
Point(2) = { radius, 0, 0, dx};
Point(3) = { 0, radius, 0, dx};
Point(4) = {-radius, 0, 0, dx};
Point(5) = { 0, -radius, 0, dx};
Point(6) = { BL*radius, 0, 0, dx};
Point(7) = { 0, BL*radius, 0, dx};
Point(8) = {-BL*radius, 0, 0, dx};
Point(9) = { 0, -BL*radius, 0, dx};
// Create cylinder and region around the cylinder BL
Circle(10) = {2, 1, 3};
Circle(11) = {3, 1, 4};
Circle(12) = {4, 1, 5};
Circle(13) = {5, 1, 2};
Circle(14) = {6, 1, 7};
Circle(15) = {7, 1, 8};
Circle(16) = {8, 1, 9};
Circle(17) = {9, 1, 6};
Line(18) = {2, 6};
Line(19) = {7, 3};
Line(20) = {4, 8};
Line(21) = {9, 5};
//- Create vertices and surfaces
Line Loop(22) = {10, 18, 14, 19};
Line Loop(23) = {19, 11, 15, 20};
Line Loop(24) = {20, 12, 16, 21};
Line Loop(25) = {21, 13, 17, 18};
Plane Surface(26) = {22};
Plane Surface(27) = {23};
Plane Surface(28) = {24};
Plane Surface(29) = {25};
//--Create bounding domain
Point(30) = { downstream, 0, 0, dxfar};
Point(31) = { downstream, height, 0, dxfar};
Point(32) = { 0, height, 0, dxfar};
Line(33) = {6, 30};
Line(34) = {30, 31};
Line(35) = {31, 32};
Line(36) = {32, 7};
Line Loop(37) = {33, 34, 35, 36, 14};
Plane Surface(38) = {37};
Point(39) = { downstream, -height, 0, dxfar};
Point(40) = { 0, -height, 0, dxfar};
Line(41) = {9, 40};
Line(42) = {40, 39};
Line(43) = {39, 30};
Line Loop(44) = {41, 42, 43, 33, 17};
Plane Surface(45) = {44};
Point(46) = { -upstream, height, 0, dxfar};
Point(47) = { -upstream, 0, 0, dxfar};
Line(48) = {32, 46};
Line(49) = {46, 47};
Line(50) = {47, 8};
Line Loop(51) = {15, 36, 48, 49, 50};
Plane Surface(52) = {51};
Point(53) = { -upstream, -height, 0, dxfar};
Line(54) = {47, 53};
Line(55) = {53, 40};
Line Loop(56) = {16, 50, 54, 55, 41};
Plane Surface(57) = {56};

If we load the script, we should see the following three-dimensional geometry.

HPCcompromise.

Geometry generation in Gmsh.

Generate mesh

Once the geometry is generated, the fluid domain can be discretized for CFD computation. At this stage, it is a good idea to be nimble and favour an iterative approach to generating the final production run mesh. It is often a good idea to start by generating a smaller mesh, visually inspecting the discretized grid, and, if needed, modifying the CAD geometry (e.g. domain size, removing smaller features of the CAD, smoothing unnecessary sharp corners, etc.) Estimates on the grid resolution requirements (computed in the last lecture) should be integrated in the definition of the final mesh.

As we discussed last lecture, grid sizing greatly influences computational costs in two ways:

  • it determines the degrees of freedom in the problem;
  • it constrains the time advancement step.

There are a couple of considerations when generating the mesh that are discussed below.

Deciding the type of mesh to use

There are two main types of mesh that are used in CFD: structured and unstructured mesh. CFD Example.

Comparison of structured and unstructured mesh.

Structured mesh

Structured meshes are (typically) hexahedra-shaped mesh organized in a logical way. Given their regular hexahedral shape, they can minimize numerical errors in flux calculation between cells. The structured mesh can also have clear advantages in terms of computational efficiency, since there is implicit knowledge of the neighboring cells. For example, if a domain is discretized using grid points, the resulting mesh can be stored in an array stores which implicitly has the connectivity of the neighboring cells. At point , we know that cell and are immediate neighbors in the direction while and will be the neighbors in the direction, and so forth. In order to use a structured mesh, the user must be able to define the structured domain in a array, which is sometimes difficult due to the geometric complexity of the domain. Another disadvantage comes from requiring a array, which means that some parts of the domain may have more points than needed. There are approaches such as block-structured meshing or a non-Cartesian meshing approach (using Jacobians) but these fall outside the scope of the present course. Although many academic codes can take full advantage of the structured mesh, most of the general purpose CFD codes will store and treat structured meshes in the exact same way as unstructured meshes. In these cases, the only advantage is in reducing the numerical error.

Most commercial and open-source CFD codes, such as SU2 and OpenFoam, permit the use of structured meshes but maintain an unstructured data structure for the computation of the interface fluxes.

Unstructured mesh

Most finite-volume CFD solvers are based on unstructured grids. In this case, the mesh information is not stored in a array, but in a list of points and the relational database that contains the information of the neighboring cells for flux computations. The unstructured mesh format provides more flexibility and generalizability for complex meshing scenarios.

Domain discretization

The mesh generation process will depend heavily on the toolset used and the general meshing decisions (type of mesh, region of higher resolution etc.) A small mesh can be rapidly generated locally on your laptop; but large, complex meshes will require additional computational resources. Careful planning of the mesh and a nimble iterative approach should be preferred. Simultaneously, it is always a good idea to aim to make a parametric geometry and mesh such that future changes to the grid can be done without too many problems.

Example: Cylinder in crossflow (mesh generation)

Continuing from the cylinder in crossflow example, we now focus on discretizing the fluid domain. For this example, we will use a structured mesh near the cylinder wall and an unstructured mesh elsewhere. This will enable us to minimize the error with a structured mesh where the gradients are the largest (near the wall) and save grid points in the far field with an unstructured mesh.

First, we define the number of grid points in the boundary layer (here there is no near wall clustering for simplicity), the number of points around the circumference of the cylinder, and number of points in the spanwise direction. Note that to make a structured mesh in Gmsh, we construct Transfinite Lines with which we create Transfinite Surface.

gmsh_cylinder.geo
[...]
Transfinite Line{18, 19} = nBL;
Transfinite Line{10, 14} = nCirc;
Transfinite Surface{26};
Recombine Surface{26};
Transfinite Line{19, 20} = nBL;
Transfinite Line{11, 15} = nCirc;
Transfinite Surface{27};
Recombine Surface{27};
Transfinite Line{20, 21} = nBL;
Transfinite Line{12, 16} = nCirc;
Transfinite Surface{28};
Recombine Surface{28};
Transfinite Line{21, 18} = nBL;
Transfinite Line{13, 17} = nCirc;
Transfinite Surface{29};
Recombine Surface{29};
Recombine Surface{38};
Recombine Surface{45};
Recombine Surface{52};
Recombine Surface{57};
num[]=Extrude {0,0,-width} {Surface{26, 27, 28, 29, 38, 45, 52, 57}; Layers{nZ}; Recombine;};
Coherence Mesh;

If this mesh were to be used in a CFD simulation, we would additionally need to define the boundaries of the computational domain (done in the final example in the class), for example:

Terminal window
Physical Surface("FREESTREAM", 96) = {76, 85, 84, 88, 87, 80, 81, 75};
Physical Surface("SIDES", 97) = {52, 38, 45, 57, 89, 82, 78, 86, 26, 29, 28, 27, 70, 73, 66, 62};
Physical Surface("WALL", 98) = {71, 69, 63, 58};
Physical Volume("VOLUME", 99) = {7, 5, 6, 8, 1, 2, 4, 3};

For now, we can generate the mesh in Gmsh and obtain:

HPCcompromise.

Generated mesh near cylinder.
HPCcompromise.
Close-up of the mesh near the cylinder.

This mesh can then be exported from Gmsh in a format that can be read by the CFD solver.

Assessing the mesh quality

Assessing the mesh quality prior to a large scale simulation can avoid lengthy iterations on HPC systems (copying mesh over to HPC system, waiting in queue, assessing error, etc.). These mesh checks can typically be done within the meshing tool or in standalone mesh assessments scripts (for example, *checkMesh * in openFoam). The mesh assessment will typically report a number of different metrics, including the following:

  • Minimum and maximum mesh size: This information does not (necessarily) affect the quality assessment, but can provide useful insight for the simulation. As many time advancement methods are constrained by the CFL number, an unreasonably small mesh may unnecessarily constrain the time-advancement of the simulation. Especially for complex geometry, the assessment of the minimal mesh size with respect to the required resolution may highlight the need to revisit the mesh generation prior to running the simulation.

  • Aspect ratio: The aspect ratio corresponds to the ratio of the smallest to the largest edge length of the cells.


This formula is primarily for hexaheadral meshes; a slight modification of this formula (using an internal sphere) is used for tetrahedral or other mesh geometries. This computation is conducted in each cell of the domain and the maximum value is presented. CFD Example.

Illustration of the aspect ratio of the mesh.

  • Mesh orthogonality: Orthogonality is a measure of the angle between the vector of the face normal and the connecting line between two neighboring cells. In structured meshes, the orthogonality is null (assuming no non-cartesian mapping), for unstructured meshes, this value can be large, although below 90 degrees. High mesh orthogonality can lead to numerical errors in the flux calculation and numerical instability in the CFD computation.

CFD Example.

Illustration of the aspect ratio of the mesh.

  • Volume ratio: This metric reveals the largest volumes ratio between neighboring cells. Strong differences in cell size can result in large numerical errors and, thus, instability of the simulation. The sensitivity of this parameter depends on a number of factors, such as the order of the numerical scheme. If this value is too large, a smoother transition should be considered.

where represents the volume of the th grid.

CFD Example.

Illustration of the volume ratio in the mesh.

  • Skewness: Skewness is a measure of the departure from perfectly perpendicular vertex angles of the mesh (for hexahedral meshes). The definition for non-hexahedral meshes is slightly more involved (and not covered herein) but the basic idea remains the same.

CFD Example.

Illustration of the mesh skewness.

General meshing metrics can be summarized as follow:

Mesh qualityMaximum value acceptable value
Aspect ratio20
Orthogonality85 deg
Volume ratio80
Skewness0.85

These values are meant to provide general guidance for the mesh quality; we may still get a high-quality simulation despite not meeting these mesh quality criteria.

Example: Cylinder in crossflow (check mesh)

Now that the mesh is generated and output, we can check the quality of the final mesh. Here, we explore two different mesh checking tools, namely: (1) the native Gmsh mesh statistics, (2) the built-in SU2 mesh checker.

  1. Native Gmsh mesh statistics: Most meshing tools have mesh quality checks built in. Gmsh also has some limited statistics that roughly align with the above-mentioned. By calling Tool->Statistics, we have access to the following information:
  • SICN: signed inverse condition number
  • Gamma: inscribed radius / circumscribed radius
  • SIGE: signed inverse error on the gradient of solution

These quantities can also be visualized, and corrections can be made to the mesh prior to simulating the final results. Using the checkMesh tool in openFoam, for example, can provide even greater statistical insight with the metrics shown above. CFD Example.

Built-in mesh checker in Gmsh.

  1. Built-in SU2 mesh checker: An alternative option is to use the check mesh that is included in most CFD solvers. For this example, we use SU2 which runs a check mesh prior to starting the simulation. From the mesh generated above, we get the following output:
Terminal window
------------------- Geometry Preprocessing ( Zone 0 ) -------------------
Three-dimensional problem.
50826 grid points.
41665 volume elements.
3 surface markers.
900 boundary elements in index 0 (Marker = FREESTREAM).
16666 boundary elements in index 1 (Marker = SIDES).
480 boundary elements in index 2 (Marker = WALL).
41665 hexahedra.
[...]
+--------------------------------------------------------------+
| Mesh Quality Metric| Minimum| Maximum|
+--------------------------------------------------------------+
| Orthogonality Angle (deg.)| 64.3865| 90|
| CV Face Area Aspect Ratio| 1.01795| 100.498|
| CV Sub-Volume Ratio| 1.00075| 5.29335|
+--------------------------------------------------------------+

Configure numerical setup

The final stage of preprocessing is setting up the case.

  • Linking the mesh to the CFD solver
  • Setting up the initial conditions of the problem
  • Setting up the boundary conditions
  • Determining the governing equations (generally Euler or Navier-Stokes), state equations, and any other multiphysics
  • Selecting the models (e.g. turbulence, acoustics, combustion)
  • Select the decomposition of the domain for parallel computing

As these are case-specific, we will investigate these steps during the final example in this section.

Summative example: preprocessing the BFS

We continue the example of the backward facing step by undertaking the preprocessing steps.

Construct domain

The size of the computational domain was determined in the previous class; based on these values, we can create the geometry that will be used. To make the mesh easily parametrizable, we define the important dimensions as variables in the Gmsh script:

bfs_200k.geo
// Gmsh project created on Mon May 29 13:48:18 2023
SetFactory("OpenCASCADE");
// x is streamwise direction
// y is wall-normal direction
// z is spanwise direction
// origin at start of backward step midplane
// Important parameters
h = 0.0096;
Li = 10.*h;
Lx = 20.*h;
Ly = 5.*h;
Lz = 4.*h;

Similarly, we can define the number of grid points based on the previous calculations (this particular case corresponds to a very coarse simulation and not the final simulation case).

bfs_200k.geo
[...]
Nxi = 50;
Nx = 100;
Ny = 50;
Nz = 40;

Now we can use the variables to create all the points, the lines connecting the points, connecting all the lines to create surfaces, and, finally, the surfaces to create volumes.

bfs_200k.geo
[...]
Point(1) = {0, 0, 0};
Point(2) = {0, h, 0};
Point(3) = {Lx, h, 0};
Point(4) = {Lx, 0, 0};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Curve Loop(1) = {4, 1, 2, 3};
Plane Surface(1) = {1};
Point(5) = {0, h+Ly, 0};
Point(6) = {Lx, h+Ly, 0};
Line(5) = {2, 5};
Line(6) = {5, 6};
Line(7) = {6, 3};
Curve Loop(2) = {5, 6, 7, -2};
Plane Surface(2) = {2};
Point(7) = {-Li, h, 0};
Point(8) = {-Li, h+Ly, 0};
Line(8) = {2, 7};
Line(9) = {7, 8};
Line(10) = {8, 5};
Curve Loop(3) = {8, 9, 10, -5};
Plane Surface(3) = {3};

To create a structured mesh in Gmsh, we need to define transfinite curves which we discretize with the corresponding number of points (as seen in the previous example). We can then Extrude the mesh in the spanwise direction.

bfs_200k.geo
[...]
Transfinite Curve {-10, 8} = Nxi Using Progression 1.08;
Transfinite Curve {6, 2, -4} = Nx Using Progression 1.04;
Transfinite Curve {9, 5, -7} = Ny*0.5 Using Progression 1.2;
Transfinite Curve {1, 3} = Ny*0.5 Using Bump 0.2;
Transfinite Surface "*";
Recombine Surface "*";
Extrude {0, 0, -Lz*0.5} {
Surface{1, 2, 3};
Layers{Nz*0.5};
Recombine;
}
Extrude {0, 0, Lz*0.5} {
Surface{1, 2, 3};
Layers{Nz*0.5};
Recombine;
}

Finally, we can define our boundary conditions on the mesh.

bfs_200k.geo
[...]
Physical Surface("inlet") = {27, 14};
Physical Surface("outlet") = {24, 11, 20, 7};
Physical Surface("wall_in") = {26, 13};
Physical Surface("wall_ver") = {18, 5};
Physical Surface("wall_hor") = {17, 4};
Physical Surface("top") = {28, 15, 23, 10};
Physical Surface("back") = {12, 16, 8};
Physical Surface("front") = {29, 21, 25};
// Physical Surface("midplane") = {1, 2, 3};
Physical Volume("internal") = {1, 2, 3, 4, 5, 6};
Click HERE to see the entire Gmsh script
bfs_200k.geo
// Gmsh project created on Mon May 29 13:48:18 2023
SetFactory("OpenCASCADE");
// x is streamwise direction
// y is wall-normal direction
// z is spanwise direction
// origin at start of backward step midplane
// Important parameters
h = 0.0096;
Li = 10.*h;
Lx = 20.*h;
Ly = 5.*h;
Lz = 4.*h;
Nxi = 50;
Nx = 100;
Ny = 50;
Nz = 40;
Point(1) = {0, 0, 0};
Point(2) = {0, h, 0};
Point(3) = {Lx, h, 0};
Point(4) = {Lx, 0, 0};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Curve Loop(1) = {4, 1, 2, 3};
Plane Surface(1) = {1};
Point(5) = {0, h+Ly, 0};
Point(6) = {Lx, h+Ly, 0};
Line(5) = {2, 5};
Line(6) = {5, 6};
Line(7) = {6, 3};
Curve Loop(2) = {5, 6, 7, -2};
Plane Surface(2) = {2};
Point(7) = {-Li, h, 0};
Point(8) = {-Li, h+Ly, 0};
Line(8) = {2, 7};
Line(9) = {7, 8};
Line(10) = {8, 5};
Curve Loop(3) = {8, 9, 10, -5};
Plane Surface(3) = {3};
Transfinite Curve {-10, 8} = Nxi Using Progression 1.08;
Transfinite Curve {6, 2, -4} = Nx Using Progression 1.04;
Transfinite Curve {9, 5, -7} = Ny*0.5 Using Progression 1.2;
Transfinite Curve {1, 3} = Ny*0.5 Using Bump 0.2;
Transfinite Surface "*";
Recombine Surface "*";
Extrude {0, 0, -Lz*0.5} {
Surface{1, 2, 3};
Layers{Nz*0.5};
Recombine;
}
Extrude {0, 0, Lz*0.5} {
Surface{1, 2, 3};
Layers{Nz*0.5};
Recombine;
}
Physical Surface("inlet") = {27, 14};
Physical Surface("outlet") = {24, 11, 20, 7};
Physical Surface("wall_in") = {26, 13};
Physical Surface("wall_ver") = {18, 5};
Physical Surface("wall_hor") = {17, 4};
Physical Surface("top") = {28, 15, 23, 10};
Physical Surface("back") = {12, 16, 8};
Physical Surface("front") = {29, 21, 25};
// Physical Surface("midplane") = {1, 2, 3};
Physical Volume("internal") = {1, 2, 3, 4, 5, 6};

Define the mesh

In the above, we generated the domain and, using the transfinite curves, we defined the mesh resolution and stretching. For illustrative purposes, we only used a very coarse mesh. In the git repository, we have included three different mesh with varying values. Here is a visual representation of the mesh defined above.

CFD Example.

Coarse BFS mesh.

Using the equations introduced in the last lesson, we can define the characteristics of all mesh as follows:

  1. Knowing the Reynolds number (), we can estimate the friction coefficient:

  2. With the friction coefficient, we can estimate the shear stress at the wall:

  3. From which we can compute the friction velocity:

  4. Based on the friction velocity and desired , we can estimate the first cell height from the wall:

All these values are summarized in the table below and the corresponding mesh are located in the repository.

Grid description (first grid)dy (mm)Grid count
Coarse50.01240.610.12123,200
Medium2.30.01240.610.056409,120
Fine10.01240.610.024780,120

With these definitions, we can output the desired mesh into a format that is relevant for the selected CFD solver.

Checking mesh

Now we can check the mesh. In this summative example, we use the checkMesh function in OpenFoam. Note that to run the checkMesh, we need to fully setup the case in openFoam. The checkMesh provides the following information:

Mesh stats
points: 248080
internal points: 0
faces: 493640
internal faces: 245560
cells: 123200
faces per cell: 6
boundary patches: 6
point zones: 0
face zones: 0
cell zones: 0
Overall number of cells of each type:
hexahedra: 123200
prisms: 0
wedges: 0
pyramids: 0
tet wedges: 0
tetrahedra: 0
polyhedra: 0
[ ... ]
Checking geometry...
Overall domain bounding box (0 0 -0.02) (0.8 0.6 0)
Mesh has 2 geometric (non-empty/wedge) directions (1 1 0)
Mesh has 2 solution (non-empty) directions (1 1 0)
All edges aligned with or perpendicular to non-empty directions.
Boundary openness (-2.0825662e-18 -4.7665119e-17 -7.2485769e-16) OK.
Max cell openness = 8.3684791e-16 OK.
Max aspect ratio = 20.267217 OK.
Minimum face area = 1.8359327e-08. Maximum face area = 0.00013630178. Face area magnitudes OK.
Min volume = 3.6718654e-10. Max volume = 1.9504299e-07. Total volume = 0.0095748737. Cell volumes OK.
Mesh non-orthogonality Max: 43.799677 average: 7.524501
Non-orthogonality check OK.
Face pyramids OK.
Max skewness = 0.44455366 OK.
Coupled point location match (average 0) OK.

A couple points to note:

  • All checks withing checkMesh are successful
  • The mesh is fully structured with only hexahedral mesh elements

Simulation setup

The standard SA model is used for near-wall turbulence modelling while Smagorinsky LES sub-grid scale (SGS) model is implemented at wall-normal distances larger than a value specified from default wall-distance coefficient. (Refer to Molina et al (2017) for SU2 formulations). In SU2, the 2nd order dual-time stepping scheme is used for time marching method with 5 inner iterations per time step. The total simulation duration is 400ms which corresponds to roughly 10 flow through times across the stream wise direction. Results are saved every 2ms.