Introduction to fluid mechanics simulation using
the OpenFOAM® technology
« Simulation in porous media from pore to large scale »
Part II: Mesh complex geometries, application to the evaluation of permeability,
transport of passive scalars at the pore-scale
Stanford
Contact: [email protected]
November 10, 2014
http://web.stanford.edu/~csoulain/ Version 5.0
Previously in OpenFOAM training...
A case is always organized in the same way: time directory, constant directory and system
directory.
To setup a case, it is recommanded to adapt an existing tutorial.
OpenFOAM® initiation
The initial and boundary conditions are defined in the 0 directory.
For simple meshes, we can use blockMesh, otherwise we should use an external gridder or
snappyHexMesh.
Two different algorithms to solve Navier-Stokes equations : SIMPLE (simpleFoam...) and PISO
(icoFoam, pisoFoam...)
[email protected] 2
General introduction to the OpenFOAM® technology
What is OpenFOAM ?
Where one can find help and documentation ?
First simulations with OpenFOAM®
General structure of an OpenFOAM® case
#1 – Heat diffusion
OpenFOAM® initiation
#2 – Cavity
#3 – Poiseuille flow
#4 – Drainage experiment in a capillary tube
How to mesh complex geometries with OpenFOAM® ?
snappyHexMesh overview
#5 – Mesh a pore-space with snappyHexMesh
#6 – Scalar transport in porous media at the pore-scale
Programming equations with OpenFOAM®
General structure of an application
Basics of OpenFOAM programming
Heat transfer in porous media with OpenFOAM®
#7 – Create a « Darcy » solver
#8 – Temperature in porous media
#9 – Two-equations model for heat transfer in porous media
How to solve Navier-Stokes equation with OpenFOAM® ?
[email protected] 3
snappyHexMesh overview (1/2)
snappyHexMesh is an automatic and robust mesher able to grid any complex
geometry
Mesh a region inside or/and around an object described by a surface mesh
OpenFOAM® initiation
It is compatible with a lot of input formats resulting from CAD softwares or
tomography imaging (*.stl, *.obj, *.vtk …)
Maximize the number of hexahedral cells
openfoam.com
openfoam.com
[email protected] 4
snappyHexMesh overview (2/2)
OpenFOAM® initiation
openfoam.com
[email protected] 5
#5 – Mesh a pore-space (1/6)
Objective:
• Mesh the void space of a porous medium with snappyHexMesh
Void space that needs to be
wall gridded
OpenFOAM® initiation
outlet
inlet
Solid grains defined by
wall
a surface mesh file
1 Generate the surface mesh (here the solid grain).
2 Create a suitable background mesh with blockMesh. It needs to be fine enough to
have at least 10 cells in the pore-throat thickness.
3 Detect the void space, remove the cells occupied by the solid and snap them to fit
as close as possible the initial surface object with snappyHexMesh.
[email protected] 6
#5 – Mesh a pore-space (2/6)
We are going to adapt the motorBike tutorial and use an existing stl file*
$ run
$ cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike Exo5
$ cd Exo5
$ cp /data/cees/OF_training/Exo5/Exo5.stl .
$ paraview Exo5.stl
OpenFOAM® initiation
* You can also download this surface mesh file at http://web.stanford.edu/~csoulain/OF_Training/Exo5/Exo5.stl
[email protected] 7
#5 – Mesh a pore-space (3/6)
The next step consists in creating a background mesh with blockMesh. The size of this background
domain depends on the bounding box of the surface object. It can be obtained using the surfaceCheck
tool,
$ surfaceCheck Exo5.stl | grep -i 'bounding box'
$ gedit constant/polyMesh/blockMeshDict
OpenFOAM® initiation
The grid needs to be fine enough in order to
capture all the details of the pore-space.
$ blockMesh
$ paraFoam
To superimpose the background grid and the
surface mesh file, in ParaView:
Specify the boundaries top, bottom, left, right, frontAndBack
file>open>Exo5.stl
(see Part I, page 33)
[email protected] 8
#5 – Mesh a pore-space (4/6)
The void space is going to be meshed with snappyHexMesh, based on the background grid.
snappyHexMesh needs an input dictionary located in the system folder and the object file located in
constant/triSurface,
$ mv Exo5.stl constant/triSurface/.
$ gedit system/snappyHexMeshDict
OpenFOAM® initiation
The three different stages of the meshing can be performed
separately or simultaneously:
- castellatedMesh: detects the intersections between the surface
object and the background grid. It can eventually refine the
background grid at the vicinity of the object. Then it removes either the
inside or the outside of the object.
- snap: Introduces tetrahedral cells at the object boundary to match
the actual geometry.
- addLayers: Add layers of cells on the boundaries.
Insertion of the surface mesh object. Several objects may be
inserted at the same times.
The solid boundaries will be named “fixedWalls”
[email protected] 9
#5 – Mesh a pore-space (5/6)
The castellated mesh step
Set up the refinement level at the vicinity of the object.
Actually, this feature only works for 3D geometry. We can
specify zero refinements with level (0 0)
Point a location where there is void space. All
cells outside the void space will be removed.
OpenFOAM® initiation
$ snappyHexMesh
$ paraFoam
The mesh is created in a new
time step (« 1 ») directory
[email protected] 10
#5 – Mesh a pore-space (6/6)
The next step is the snapping stage to fit the STL surface as close as possible. This
stage will introduce some tetrahedral cells into the computational domain.
$ gedit system/snappyHexMeshDict
OpenFOAM® initiation
The mesh is created in another
time step (« 2 ») folder
$ snappyHexMesh
$ paraFoam
Eventually, we could have used the addLayers stage to add layers of cells around the
solid grains.
[email protected] 11
#6 – Scalar transport in the pore space (1/8)
Objectives:
• Solve the flow in the void space gridded in the previous exercise
• Estimate the permeability of the porous medium
• Solve a passive scalar transport in the void space
outlet
inlet
OpenFOAM® initiation
0.92 mm
The flow and the scalar transport are uncoupled. They can therefore be solved one
after the other.
The flow is obtained solving a Stokes problem with simpleFoam. The case can be setup
based on Exo3 (or $FOAM_TUTORIALS/incompressible/simpleFoam/pitzDaily)
$ run
$ cp -r Exo3 Exo6a
The mesh is replaced by the grid of the previous exercise and scaled to the actual size
$ rm -r constant/polyMesh
$ cp -r ../Exo5/2/constant/polymesh ./constant/.
$ transformPoints -scale '(0.01 0.01 0.01)'
[email protected] 12
#6 – Scalar transport in the pore space (2a/8)
$ gedit 0/U $ gedit 0/p
OpenFOAM® initiation
[email protected] 13
#6 – Scalar transport in the pore space (2b/8)
$ gedit system/fvSolution
Setup the fluid properties
PCG = Preconditioned
$ gedit constant/transportProperties conjugate gradient solver
for symmetric matrices
OpenFOAM® initiation
PBiCG = Preconditioned bi-
conjugate gradient solver
for asymmetric matrices
Switch off the turbulence model
The simulation will
$ gedit constant/RASProperties
stop when these
residuals will be
reached.
Relaxation factors for the
SIMPLE algorithm. The value
0.9 for U is faster for Stokes
flows.
[email protected] 14
#6 – Scalar transport in the pore space (2c/8)
$ gedit system/controlDict
OpenFOAM® initiation
Since we have specified convergence criteria in
system/fvSolution, the simulation may stop before
endTime. In that case, the latest simulated time
step will be automatically written.
[email protected] 15
#6 – Scalar transport in the pore space (3/8)
It might be useful to plot the residuals on-the-fly to check the simulation convergence. This can be
achieved by redirecting the simulation log into a file and extracting the residual values with the
following gnuplot script :
$ gedit plotResiduals
OpenFOAM® initiation
Run the simulation and make it write out a log-file
$ simpleFoam > log &
Plot the residuals convergence with gnuplot
$ gnuplot plotResiduals
[email protected] 16
#6 – Scalar transport in the pore space (4a/8)
$ paraFoam The porosity (ε) is the volume of the mesh (Vvoid) over
the volume (V) of the bounding box:
$ checkMesh | grep -i 'volume'
Vvoid= 2.93x10-12 m3
OpenFOAM® initiation
$ checkMesh | grep -i 'bounding box'
V=Lx*Ly*Lz=5.15x10-12 m3
ε = 0.57
The permeability Kxx is defined as*:
The velocity can be integrated directly from
ParaView with the filter:
filters>integrateVariables
Kxx= 1.6x10-11 m2
* Actually, we will see in Part III that it is better to estimate the permeability considering the domain as a REV with periodic boundary
conditions. [email protected] 17
#6 – Scalar transport in the pore space (4b/8)
Exo6aBis : Run the simulation with a multi-grid solver for the pressure matrix and compare the
residuals convergence.
$ gedit system/fvSolution smoothSolver = solver using a smoother for both symmetric
and asymmetric matrices
OpenFOAM® initiation
GAMG = generalised geometric-algebraic multi-grid solver.
It is often the optimal choice for solving the pressure
equation. « GAMG uses the principle of: generating a quick
solution on a mesh with a small number of cells; mapping
this solution onto a finer mesh; using it as an initial guess
to obtain an accurate solution on the fine mesh. »
[email protected] 18
#6 – Scalar transport in the pore space (5/8)
Once the flow is solved, we can use the velocity profile to transport (advection-diffusion) a
scalar T with the solver scalarTransportFoam,
OpenFOAM® initiation
For that purpose, we adapt the tutorial scalarTransportFoam/pitzDaily
$ run
$ cp -r $FOAM_TUTORIALS/basic/scalarTransportFoam/pitzDaily Exo6b
$ cd Exo6b
$ rm -r constant/polyMesh
We retreive the mesh and the resulting velocity profile from the previous simulation
$ cp -r ../Exo6a/constant/polyMesh constant/.
$ cp ../Exo6a/latestTime/U 0/.
[email protected] 19
#6 – Scalar transport in the pore space (6/8)
$ gedit 0/T $ gedit constant/transportProperties
$ gedit system/controlDict
OpenFOAM® initiation
[email protected] 20
#6 – Scalar transport in the pore space (7/8)
t=0.05s
Run the simulation
OpenFOAM® initiation
$ scalarTransportFoam
t=0.10s
Visualize the results
$ paraFoam t=0.15s
t=0.20s
[email protected] 21
#6 – Scalar transport in the pore space (8/8)
To obtain a breakthrough curve, we look for the average value at the outlet boundary
for all time steps
$ patchAverage T right > log.patchAverage
Extract the values from the log file with the following command
$ cat log.patchAverage | grep -i 'right' | cut -d' ' -f12 > log.breaktrough
OpenFOAM® initiation
Plot the breakthrough curve
$ gnuplot
gnuplot> plot 'log.breaktrough' with lines lw 4
1.2
1
Exo6bis : Plot the breakthrough curves
0.8 for different values of the diffusivity
(D=5x10-6 m2/s and D=5x10-7 m2/s)
0.6 D5e-6
D1e-6
T
D5e-7
0.4
0.2
0
0 1 2 3 4 5 6
time (s)
[email protected] 22
In the next parts...
OpenFOAM® initiation
Part III: First programs, development of a heat tranfer solver in porous media
Part IV: How to solve Navier-Stokes equations with OpenFOAM?
http://web.stanford.edu/~csoulain/
[email protected] 23