In this tutorial is presented a quite simple case of a cylinder mesh made with snappyHexMesh utility. You can realize it in many different ways (with open or close STL, with big, small or right dimensions of blockMesh and so on). All this different ways are presented below.
First of all a picture that describes the case settings (each aspect will be explained later). You can copy the files contained in motorBike tutorial contained in $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike and modify the case.
At this link you can download the whole case. It may contain errors so check all the files while reading this guide and then try to modify some parameters to see what changes in results.
In this tutorial, for educational purposes, two different STL are created:
- Close: the close STL represent the pipe with all surfaces meshed with triangles
- Open: the open STL represent the pipe only by the lateral surface (inlet and outlet faces are missing)
We will use both in the tutorial with different blockMesh.
The dimension of the cylinder are:
- base: with radius of 0.5
- height of 6 in z direction
In STL files we set just one layer name, including all surfaces, called suplat
See cube case tutorial for controlDict, fvSchemes, fvSolution and decomposeParDict.
First of all we want to create a mesh of cubes (a classic with snappy), so also the blockMesh has to be made of cubes (we will create a mesh of elongated elements after this case).
We analyze three type of blockMesh:
Is a blockMesh greater than the STL geometry especially in axial direction (z)
Just the important part of blockMeshDict is shown
To change the blockMesh just change the bold parameters
To change the blockMesh just change the bold parameters
The results is shown in this pictures, all the blockMesh little cubes have the same dimension, the total number of these cubes (especially the number in axial direction) changes from one to another blockMesh
As usual we encounter some problems in snappyHexMesh, especially in the snap part, but with some arrangements regarding the STL and blockMesh choice we can obtain a good result.
We want to analyze the snap problems, so deactivate the layer part in activation rows.
and try to run snappyHexMesh with these (semi)default values:
- we define the surface name as cylinder and recall the STL region suplat, named mysuplat;
- we set a quite high value of featureAngle to avoid high refinement zones;
- we select an internal point to obtain internal mesh
- we set quite improved values of snap controls (improved compared to default values)
At first we try to run snappyHexMesh with the close STL with different blockMesh, the snappyHexMeshDict file doesn't change, only change the files into constant/polyMesh directory (the blockMesh files)
- snappy doesn't recognize the sharp edges and can't snap well the mesh points to the surface
- we get a mesh thickening also towards the inlet and outlet faces, while often, in pipe simulations, you just want a lateral walls thickening.
The first problem is very serious and difficult to resolve (by now I don't know what to do), the second can be solved defining two regions in STL file (one for lateral walls and one for inlet and outlet faces), setting a 0 refinement level for the whole surface and a single refinement for the wall region.
The result is shown in this picture
You can try to improve snap controls (decreasing tolerance and increasing all other options) but the results doesn't change
With the right blockMesh the mesh quality improves on sharp edges, but we still have some imperfections (honestly they could be attributed to the bad mesh quality in STL file near the edge).
We still have the wrong thickening problem, but it is not a big deal and we can solve it. This is a slice that shows the thickening problem.
With a blockMesh smaller than the cylinder we resolve the sharp edges problems and the wrong thickening problems, but (obviously) we obtain a smaller mesh. So if you want to simulate the flow in a 30 meters pipe, you have to make an STL file of 40 meters and then the blockMesh will cut your geometry. It is not a disaster, but not so convenient.
By the way the results are great (but the cylinder is smaller)
The best option with a close STL is to use a small blockMesh (smaller than the geometry), but you have to draw a bigger STL that will be cut by the blockMesh in snappyHexMesh process. Also the right blockMesh could work well, but you have to draw a very refined STL especially near sharp edges.
With a simple geometry like our cylinder, we can try to run snappyHexMesh using an open STL, to avoid the previous (close STL) problems. This STL has no inlet and outlet faces, but only the lateral surface (called suplat in STL file)
We can't use this blockMesh because it is greater than the geometry and the STL surfaces can't subdivide it in two distinct regions, so we can't obtain the internal mesh.
The mesh obtained with a right blockMesh is perfect. No evident problems are found: sharp edges are fine, the thickening (a problem in close STL + right blockMesh) is correct and the cylinder has the proper length.
The mesh is very similar to the one obtained with close STL + small blockMesh, with the same pro and con.
We activate the addLayer controls in activation rows and set the snappyHexMeshDict file:
- we decide to add three layers on mysuplat sub-region with relative sizes
- final layer thickness is 0.7 times the near cells thickness, with an expansion ratio of 1.1
- we increase the maxFaceThicknessRatio and the maxThicknessToMedialRatio to help layer addition also in presence of highly warped cells
Near the sharp edges (badly meshed) the layers are unacceptable. This problem stems from the bad mesh previously created.
Also in this case the layer addition doesn't run very well, especially in proximity of inlet outlet faces (because of the bad previously mesh)
We analyze the layer addition on mesh obtained with open STL. We don't consider big blockMesh because we didn't obtain any mesh with open STL + big blockMesh
Perfect layer addition. Nothing to say
A common problem of the previous mesh is the high number of cells. Our case is very simple and grossly meshed, but in real cases, using cubes, we will obtain a very high number of elements, hence slow simulations.
To solve this problem we can create a blockMesh with elongated elements (parallelepipeds), snappyHexMesh will halve all dimensions obtaining four similar parallelepipeds by the first one.
This is a common solution in pipe flow analysis, but with too elongated elements we may obtain elements with nonOrthoFaces.
In order to create a case with elongated elements (called axial case) we use the best couple obtained in previous simulations: open STL + right blockMesh with two different blockMesh
- Axial : slightly elongated elements
- Axial extreme : heavily elongated elements, minor number of elements, but presence of nonOrthoFaces
The snappyHexMeshDict file is similar to the one used for previous case. Just change a control parameter:
- we disable the control on nonOrthoFaces because if snappyHexMesh find some of them it tries to repair them and fail, so doesn't add layers (5.4.7 OpenFOAM UG). We ignore the control on them but we have to keep in mind that we could have nonOrthoFaces if we encounter problems solving a case with this mesh.
The result is very nice, the layer addition worked properly and we managed to keep a lower number of elements
In this slice you can see the parallelepipeds elements split
In this case the number of cells decreases , the mesh is very handy but we risk getting nonOrthoFaces. Moreover the number of cells between levels isn't six (as we set) but snappy mess a little in boundary refinement zones. We should check the mesh.
The checkMesh is an useful utility which finds any errors in our mesh. You can launch it by typing checkMesh in a command line, you can also add the -latestTime options to check just the latest timestep created
We should control also the previous mesh, which we called ''perfect'', to see if it is ready for a simulation process or not. just type checkMesh -latestTime in open STL + right blockMesh folder and read the output. It should be like this:
The checkMesh failed, because of the presence of nonAlignedEdges. This is because snappy creates some default patch (called defaultFaces, you can see it in output) and set to empty.
- defaultFaces is a patch containing inlet and outlet faces. If we don't care to distinguish these faces we can simply edit 3/polyMesh/boundary file and set defaultFaces as a patch, not empty
type patch; // this was empty before our change
If we run checkMesh now it should worked well.
- If we care to distinguish from inlet and outlet faces (as usual) we should run autoPatch utility on third step (latest). First of all modify system/controlDict file and set
so autoPatch will work on mesh contained in 3 folder and will create a 4 folder with patched mesh. To run autoPatch type autoPatch 75 in a command line. 75 is the featureAngle used for patching (play on this if autoPatch doesn't work properly). The utility will create a new boundary file in 4/polyMesh folder:
autoPatch keeps old patches and add the new; auto0 and auto1 are inlet and outlet, while auto2 represents the walls. We should fix it
You could set wall type for wall patch if you will use wall functions on this surfaces.
Now the checkMesh should run properly.
Axial case (open STL)
If we run checkMesh on axial case, we obtain an output very similar to the open STL case; checkMesh warns us of the presence of nonAlignedEdges (is an intrinsic problem of snappyHexMesh) we could fix this as shown before.
If we try to run checkMesh on axial_extreme case the output is:
checkMesh warn us of the presence of 672 nonOrthoFaces besides the nonAlignedEdges.