Openfoamtut 1
Openfoamtut 1
Revision 1-2020
JG
Acknowledgements
This training material and tutorials are based upon personal experience, OpenFOAM® source
code, OpenFOAM® user guide, OpenFOAM® programmer’s guide, and presentations from
previous OpenFOAM® training sessions and OpenFOAM® workshops.
We gratefully acknowledge the following OpenFOAM® users for sharing online their material or for
giving us their consent to use their material:
• Edoardo Alinovi.
• Matteo Bargiacchi.
• Mattia Cavaiola.
• Peyman Davvalo Khongar.
• Sehrish Naqvi.
• Damiano Natali.
• Stefano Olivieri.
• Biniyam Sishah.
• Giuseppe Zampogna.
On the training material
The following typographical conventions are used in this
training material
• Text in Courier new font indicates Linux commands that should be typed literally by the user
in the terminal.
• Text in Courier new bold font indicates directories.
• Text in Courier new italic font indicates human readable files or ascii files.
• Text in Arial bold font indicates program elements such as variables, function names, classes,
statements and so on. It also indicate environment variables, and keywords. They also
highlight important information.
• Text in Arial underline in blue font indicates URLs and email addresses.
• This icon indicates a warning or a caution.
• This icon indicates a tip, suggestion, or a general note.
• This icon indicates a folder or directory.
• This icon indicates a human readable file (ascii file).
• This icon indicates that the figure is an animation (animated gif).
• These characters $> indicate that a Linux command should be typed literally by the user in the
terminal.
On the training material
The following typographical conventions are used in this
training material
• Large code listing, ascii files listing, and screen outputs can be written in
a square box, as follows:
1 #include <iostream>
2 using namespace std;
3
4 // main() is where program execution begins. It is the main function.
5 // Every program in c++ must have this main function declared
6
7 int main ()
8 {
9 cout << "Hello world"; //prints Hello world
10 return 0; //returns nothing
11 }
• To uncompress the tutorials go to the directory where you copied the training material and then type in the
terminal,
• $> tar –zxvf file_name.tar.gz
• In every single tutorial, you will find the file README.FIRST. In this file you will find the general instructions of
how to run the case. You will also find some additional comments.
• In some cases, you will also find additional files with the extension .sh. These files can be used to run the
case automatically, but we highly recommend to open the README.FIRST file and type the commands in the
terminal, in this way you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
• You will find the automatic scripts in the cases explained in the lectures notes and some random cases.
• A word of caution, use the tutorials included in the training material just for recreational, instructional,
or learning purposes and not for validation, benchmarking or as standard practices.
On the training material
Exercises
• At the end of each section, you will find an exercise section.
• The exercise section is optional, self-paced, and do it at anytime.
• The proposed exercises are designed to test your knowledge and to
reinforce the concepts addressed during the lectures.
• All the concepts to be addressed in the exercise sections have been treated
in the lecture notes, so the reader should not have problems answering the
questions.
• If you have doubts, do not hesitate in asking.
• To help you answering the exercises, we might give you a few tips.
• And if it is necessary, the solution will be given.
Housekeeping issues
• What OpenFOAM® version are we going to use?
• During this training we are going to use OpenFOAM® version 8.
• The one developed by OpenCFD Ltd (http://www.openfoam.org/).
Week 2.
• Solid modeling using Onshape, mesh generation, mesh quality assessment, qualitative and quantitative
postprocessing, scientific visualization
Week 3.
• Introduction to the finite volume method, numerical playground, best standard practices in CFD and
OpenFOAM®, implementing boundary conditions and initial conditions using codeStream
Week 4.
• Implementing boundary conditions and initial conditions using codeStream (continuation), advanced physical
models (turbulence, multiphase, compressible flows, dynamic meshes, source terms).
Week 5.
• Advanced physical models (continuation), extra topics (supplements), tips and tricks, closing remarks
Training agenda
Week 1.
• Module 0, Module 1, Module 4
Week 2.
• Module 2, Module 3, Module 5
Week 3.
• Module 6, Module 7
Week 4.
• Module 7, Module 8
Week 5.
• Module 8, extra topics
Training agenda
• The training agenda is organized in such a way that we will address the whole CFD simulation workflow.
Module 1
OpenFOAM® overview – First tutorial –
Working our way in OpenFOAM®
1
Roadmap
2
OpenFOAM® brief overview
General description:
• OpenFOAM® stands for Open Source Field Operation and Manipulation.
• OpenFOAM® is first and foremost a C++ library used to solve partial
differential equations (PDEs), and ordinary differential equations (ODEs).
• It comes with several ready-to-use or out-of-the-box solvers, pre-processing
utilities, and post-processing utilities.
• It is licensed under the GNU General Public License (GPL). That means it is
freely available and distributed with the source code.
• It can be used in massively parallel computers. No need to pay for separate
licenses.
• It is under active development.
• It counts with a wide-spread community around the world (industry,
academia and research labs).
3
OpenFOAM® brief overview
Multi-physics simulation capabilities:
• OpenFOAM® has extensive multi-physics simulation capabilities, among
others:
• Computational fluid dynamics (incompressible and compressible flows).
• Computational heat transfer and conjugate heat transfer.
• Combustion and chemical reactions.
• Multiphase flows and mass transfer.
• Particle methods (DEM, DSMC, MD) and lagrangian particles tracking.
• Stress analysis and fluid-structure interaction.
• Rotating frames of reference, arbitrary mesh interface, dynamic mesh
handling, and adaptive mesh refinement.
• 6 DOF solvers, ODE solvers, computational aero-acoustics,
computational electromagnetics, computational solid mechanics, MHD.
4
OpenFOAM® brief overview
Physical modeling library:
• OpenFOAM® comes with many physical models, among others:
• Extensive turbulence modeling capabilities (RANS, DES and LES).
• Transport/rheology models. Newtonian and non-Newtonian viscosity
models.
• Thermophysical models and physical properties for liquids and gases.
• Source terms models.
• Lagrangian particle models.
• Interphase momentum transfer models for multiphase flows.
• Combustion, flame speed, chemical reactions, porous media, radiation,
phase change.
5
OpenFOAM® brief overview
Under the hood you will find the following:
• Finite Volume Method (FVM) based solver.
• Collocated polyhedral unstructured meshes.
• Second order accuracy in space and time. Many discretization schemes
available (including high order methods).
• Steady and transient solvers available.
• Pressure-velocity coupling via segregated methods (SIMPLE and PISO).
• But coupled solvers are under active development.
• Massive parallelism through domain decomposition.
• It comes with its own mesh generation tools.
• It also comes with many mesh manipulation and conversion utilities.
• It comes with many post-processing utilities.
• All components implemented in library form for easy re-use.
6
OpenFOAM® brief overview
OpenFOAM® vs. Commercial CFD applications:
• OpenFOAM® capabilities mirror those of commercial CFD applications.
• The main differences with commercial CFD applications are:
• There is no native GUI.
• It does not come with predefined setups. The users need to have a basic
understanding of the CFD basics and be familiar with OpenFOAM® command
line interface (CLI).
• Knowing your way around the Linux bash shell is extremely useful.
• It is not a single executable. Depending of what you are looking for, you will
need to execute a specific application from the CLI.
• It is not well documented, but the source code is available.
• Access to complete source = no black magic. But to understand the source
code you need to know object-oriented programming and C++.
• Solvers can be tailored for a specific need, therefore OpenFOAM® is ideal for
research and development.
• It is free and has no limitation on the number of cores you can use.
7
OpenFOAM® brief overview
Developing new solvers (in case you need it):
• As the user has complete access to the source code, she/he has total
freedom to modify existing solvers or use them as the starting point for new
solvers.
• New solvers can be easily implemented using OpenFOAM® high level
programming, e.g.:
solve
(
fvm::ddt(T)
+ fvm::div(phi,T)
- fvm::laplacian(nu,T)
==
0
);
8
OpenFOAM® brief overview
9
Roadmap
10
OpenFOAM® directory organization
$WM_PROJECT_DIR If you installed OpenFOAM® in the default location, the
├── Allwmake environment variable $WM_PROJECT_DIR should point
├── applications to the following directory (depending on the installed
version):
├── bin
├── COPYING
├── doc $HOME/OpenFOAM/OpenFOAM-8
├── etc or
├── platforms $HOME/OpenFOAM/OpenFOAM-dev
├── README.org
├── src In this directory you will find all the files containing
├── tutorials OpenFOAM® installation.
└── wmake
In this directory you will also find additional files (such as
README.org, COPYING, etc.), but the most important
one is Allwmake, which compiles OpenFOAM®.
11
OpenFOAM® directory organization
$WM_PROJECT_DIR OpenFOAM® environment variables
├── Allwmake
├── applications The entries starting with the symbol $ are environment
├── bin variables. You can find out the value of an environment
├── COPYING variable by echoing its value, for example:
├── doc $> echo $WM_PROJECT_DIR
├── etc
├── platforms
will print out the following information on the terminal,
├── README.org
$HOME/OpenFOAM/OpenFOAM-8
├── src
├── tutorials
└── wmake To list all the environment variables type in the terminal
window,
$> env
14
OpenFOAM® directory organization
The applications directory
$WM_PROJECT_DIR/applications
├── Allwmake
├── solvers
├── test
└── utilities
15
OpenFOAM® directory organization
The bin directory
$WM_PROJECT_DIR/bin/ Let us visit the bin directory:
├── foamCleanPolyMesh
• The bin directory contains many shell
├── foamCleanTutorials scripts, such as foamNew, foamLog,
├── foamCloneCase foamJob, foamNewApp, etc.
├── foamJob
├── foamLog • This directory also contains the script
paraFoam that will launch paraView.
├── foamMonitor
├── foamNew
├── foamNewApp
├── foamNewBC
├── foamNewFunctionObject
├── paraFoam
├── ...
└── tools
17
OpenFOAM® directory organization
The etc directory
$WM_PROJECT_DIR/etc/ Let us visit the etc directory:
├── bashrc
• The etc directory contains the environment
├── caseDicts
files, global OpenFOAM® instructions,
├── cellModels templates, and the default thermochemical
├── codeTemplates database thermoData/thermoData
├── config.csh
• In the directory caseDicts, you will find many
├── config.sh
templates related to the input files used to setup
├── controlDict a case in OpenFOAM®. We recommend you
├── cshrc take some time and explore these files.
├── paraFoam
├── README.org • It also contains the super dictionary
controlDict, where you can set several
├── templates debug flags and the defaults units.
└── thermoData
18
OpenFOAM® directory organization
The platforms directory
$WM_PROJECT_DIR/platforms/
├── linux64GccDPInt32Opt
│ ├── applications
│ ├── bin
│ ├── lib
│ └── src
└── linux64GccDPInt32OptSYSTEMOPENMPI
└── src
• If you want to locate a file inside $WM_PROJECT_DIR that contains the string fvPatch in its
name, you can proceed as follows,
• $> find $WM_PROJECT_DIR –type f -name “*fvPatch*”
• If you want to find a string inside a file, you can use the grep command.
• For example, if you want to find the string LES inside all the files within the directory
$FOAM_SOLVERS, you can proceed as follows,
• $> grep -r -n “LES” $FOAM_SOLVERS
The argument -r means recursive and -n will output the line number.
25
OpenFOAM® directory organization
Looking for information in OpenFOAM® source code
• Dictionaries are input files required by OpenFOAM®.
• As you can imagine, there are many dictionaries in OpenFOAM®. The easiest way to find all of
them is to do a local search in the installation directory as follows,
• For instance, if you are interested in finding all the files that end with the Dict word in the
tutorials directory, in the terminal type:
• $> find $FOAM_TUTORIALS -name “*Dict”
(Case sensitive search)
• $> find $FOAM_TUTORIALS –iname ‘*dict’
(Non-case sensitive search)
• When given the search string, you can use single quotes ‘ ’ or double-quotes “ ” (do not mixed
them).
• We recommend to use single quotes, but it is up to you.
26
OpenFOAM® directory organization
Looking for information in OpenFOAM® source code
• A few more advanced commands to find information in your OpenFOAM® installation.
• To find which tutorial files use the boundary condition slip:
• $> find $FOAM_TUTORIALS -type f | xargs grep -sl ‘ slip’
This command will look for all files inside the directory $FOAM_TUTORIALS, then the
output is used by grep to search for the string slip.
• To find where the source code for the boundary condition slip is located:
• $> find $FOAM_SRC -name “*slip*”
27
OpenFOAM® directory organization
Environment variables
• Remember, OpenFOAM® uses its own environment variables.
• OpenFOAM® environment settings are contained in the OpenFOAM-8/etc directory.
• If you installed OpenFOAM® in the default location, they should be in:
• $HOME/OpenFOAM/OpenFOAM-8/etc
• If you are running bash or ksh (if in doubt type in the terminal echo $SHELL), you sourced the
$WM_PROJECT_DIR/etc/bashrc file by adding the following line to your $HOME/.bashrc
file:
• source $HOME/OpenFOAM/OpenFOAM-8/etc/bashrc
28
Roadmap
29
Directory structure of an OpenFOAM® application/utility
32
Roadmap
33
Applications/utilities in OpenFOAM®
• OpenFOAM® is not a single executable.
• Depending of what you want to do, you will need to use a specific application and
there are many of them.
• If you are interested in knowing all the solvers, utilities, and libraries that come with
your OpenFOAM® distribution, read the applications and libraries section in the user
guide (chapter 3).
• In the directory $WM_PROJECT_DIR/doc you will find the documentation in pdf
format.
• You can also access the online user guide. Go to the link
http://cfd.direct/openfoam/user-guide/#contents, then go to chapter 3 (applications
and libraries).
• If you want to get help on how to run an application, type in terminal
• The option –help will not run the application; it will only show all the options
available.
• You can also get all the help you want from the source code. 34
Applications/utilities in OpenFOAM®
• You will find all the applications in the directory $FOAM_SOLVERS (you can use the
alias sol to go there).
• You will find all the utilities in the directory $FOAM_UTILITIES (you can use the alias
util to go there).
• For example, in the directory $FOAM_SOLVERS, you will find the directories containing
the source code for the solvers available in the OpenFOAM® installation (version 8):
• basic • financial
• combustion • heatTransfer
• compressible • incompressible
• discreteMethods • lagrangian
• DNS • multiphase
• electromagnetics • stressAnalysis
• adjointShapeOptimizationFoam • pimpleFoam
• boundaryFoam • pisoFoam
• icoFoam • shallowWaterFoam
• nonNewtonianIcoFoam • simpleFoam
• Inside each directory, you will find a file with the extension *.C and the same name
as the directory. This is the main file, where you will find the top-level source code
and a short description of the solver or utility.
• For example, in the file incompressible/icoFoam/icoFoam.C you will find the
following description:
36
Applications/utilities in OpenFOAM®
• Remember, OpenFOAM® is not a single executable.
• You will need to find the solver or utility that best fit what you want to do.
• A few solvers that we will use during this course:
• icoFoam: laminar incompressible unsteady solver. Be careful, do not use this
solver for production runs as it has many limitations.
• simpleFoam: incompressible steady solver for laminar/turbulent flows.
• pimpleFoam: incompressible unsteady solver for laminar/turbulent flows.
• rhoSimpleFoam: compressible steady solver for laminar/turbulent flows.
• rhoPimpleFoam: unsteady compressible solver for (laminar/turbulent flows.
• interFoam: unsteady multiphase solver for separated flows using the VOF
method (laminar and turbulent flows).
• laplacianFoam: Laplace equation solver.
• potentialFoam: potential flow solver.
• scalarTransportFoam: steady/unsteady general transport equation solver.
37
Applications/utilities in OpenFOAM®
• Take your time and explore the source code.
• Also, while exploring the source code be careful not to add unwanted modifications in
the original installation.
• If you modify the source code, be sure to do the modifications in your user directory
instead of the main source code.
38
Roadmap
39
Directory structure of an OpenFOAM® case
Directory structure of a general case
case_name • OpenFOAM® uses a very particular directory
├── 0 structure for running cases.
│ ├── p • You should always follow the directory structure,
│ └── U otherwise, OpenFOAM® will complain.
├── constant • To keep everything in order, the case directory is
│ ├── polyMesh often located in the path
$WM_PROJECT_USER_DIR/run.
│ │ ├── boundary
│ │ ├── faces • This is not compulsory but highly advisable. You can
copy the case files anywhere you want.
│ │ ├── neighbour
• The name of the case directory is given by the user
│ │ ├── owner (do not use white spaces or strange symbols).
│ │ └── points
• Depending of the solver or application you would like
│ └── transportProperties to use, you will need different files in each sub-
├── system directory.
│ ├── controlDict • Remember, you always run the applications and
│ ├── fvSchemes utilities in the top level of the case directory (the
│ └── fvSolution directory with the name case_name). Not in the
directory system, not in the directory constant, not
└── time_directories in the directory 0.
40
Directory structure of an OpenFOAM® case
Directory structure of a general case
case_name case_name: the name of the case directory is given by
├── 0 the user (do not use white spaces or strange
│ ├── p symbols).
41
Roadmap
42
Running my first OpenFOAM® case setup blindfold
Before we start – Always remember the directory structure
case_name
├── 0
├── constant
│ └── polyMesh
├── system
└── time_directories
• To keep everything in order, the case directory is often located in the path
$WM_PROJECT_USER_DIR/run.
• This is not compulsory but highly advisable, you can put the case in any directory of your preference.
• The name of the case directory if given by the user (do not use white spaces).
• You run the applications and utilities in the top level of this directory.
• The directory system contains run-time control and solver numerics.
• The directory constant contains physical properties, turbulence modeling properties, advanced physics
and so on.
• The directory constant/polyMesh contains the polyhedral mesh information.
• The directory 0 contains boundary conditions (BC) and initial conditions (IC).
43
Running my first OpenFOAM® case setup blindfold
Before we start – Setting OpenFOAM® cases
• As you will see, it is quite difficult to remember all the dictionary files needed to run
each application.
• It is even more difficult to recall the compulsory and optional entries of each input file.
• When setting a case from scratch in OpenFOAM®, what you need to do is find a
tutorial or a case that close enough does what you want to do and then you can adapt
it to your physics.
• Having this in mind, you have two sources of information:
• $WM_PROJECT_DIR/tutorials
(The tutorials distributed with OpenFOAM®)
• $PTOFC
(The tutorials used during this training)
• If you use a GUI, things are much easier. However, OpenFOAM® does not come
with a native GUI interface.
• We are going to do things in the hard way (and maybe the smart way), we are going
to use the Linux terminal
44
Running my first OpenFOAM® case setup blindfold
Flow in a lid-driven square cavity – Re = 100
Incompressible flow
45
Running my first OpenFOAM® case setup blindfold
Workflow of the case
blockMesh
icoFoam functionObjects
sampling paraview
46
Running my first OpenFOAM® case setup blindfold
A word of caution about the solver icoFoam
47
Running my first OpenFOAM® case setup blindfold
At the end of the day, you should get something like this
High-Re Solutions for incompressible flow using the navier-stokes equations and a multigrid method
U. Ghia, K. N. Ghia, C. T. Shin.
Journal of computational physics, 48, 387-411 (1982) 49
Running my first OpenFOAM® case setup blindfold
$PTOFC/101OF/cavity2D
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
50
Running my first OpenFOAM® case setup blindfold
Loading OpenFOAM® environment
• If you are using the lab workstations, you will need to source OpenFOAM® (load
OpenFOAM® environment).
• To use PyFoam (a plotting utility) you will need to source it. Type in the terminal:
• $> anaconda3
• Remember, every time you open a new terminal window you need to source
OpenFOAM® and PyFoam.
• Also, you might need to load OpenFOAM® again after loading PyFoam.
• By default, when installing OpenFOAM® and PyFoam you do not need to do this.
This is our choice as we have many things installed and we want to avoid conflicts
between applications.
51
Running my first OpenFOAM® case setup blindfold
What are we going to do?
• We will use the lid-driven square cavity tutorial as a general example to show you how to set up
and run solvers and utilities in OpenFOAM®.
• In this tutorial we are going to generate the mesh using blockMesh.
• After generating the mesh, we will look for topological errors and assess the mesh quality. For
this we use the utility checkMesh. Later on, we are going to talk about what is a good mesh.
• Then, we will find the numerical solution using icoFoam, which is a transient solver for
incompressible, laminar flow of Newtonian fluids. By the way, we hope you did not forget where
to look for this information.
• And we will finish with some quantitative post-processing and qualitative visualization using
paraFoam and OpenFOAM® utilities.
• While we run this case, we are going to see a lot of information on the screen (standard output
stream or stdout), but it will not be saved. This information is mainly related to convergence of
the simulation, we will talk about this later on.
• A final word, we are going to use the solver icoFoam but have in mind that this is a very basic
solver with no modeling capabilities and limited post-processing features.
• Therefore, is better to use pisoFoam or pimpleFoam which are equivalent to icoFoam but
with many more features.
52
Running my first OpenFOAM® case setup blindfold
Running the case blindfold
• Let us run this case blindfold.
• Later we will study in detail each file and directory.
• Remember, the variable $PTOFC is pointing to the path where you unpacked the
tutorials.
• You can create this environment variable or write down the path to the directory.
• In the terminal window type:
1. $> cd $PTOFC/101OF/cavity
2. $> ls –l
3. $> blockMesh
4. $> checkMesh
5. $> icoFoam
6. $> postProcess -func sampleDict -latestTime
7. $> gnuplot gnuplot/gnuplot_script
8. $> paraFoam
53
Running my first OpenFOAM® case setup blindfold
Running the case blindfold
• In step 1 we go to the case directory. Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
• In step 2 we just list the directory structure (this step is optional). Does it look familiar to you? In
the directory 0 you will the initial and boundary conditions, in the constant directory you will
find the mesh information and physical properties, and in the directory system you will find the
dictionaries that controls the numerics, runtime parameters and sampling.
• In step 3 we generate the mesh.
• In step 4 we check the mesh quality. We are going to address how to assess mesh quality later
on.
• In step 5 we run the simulation. This will show a lot information on the screen, the standard
output stream will not be saved.
• In step 6 we use the utility postProcess to do some sampling only of the last saved solution
(the latestTime flag). This utility will read the dictionary file named sampleDict located in
the directory system.
• In step 7 we use a gnuplot script to plot the sampled values. Feel free to take a look and reuse
this script.
• Finally, in step 8 we visualize the solution using paraFoam. In the next slides we are going to
briefly explore this application.
54
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam
Menu Bar
Toolbars
Pipeline Browser
Properties panel
Apply button
Press this button to
load the case or to
apply a filter
3D View/Canvas
Advanced Toggle
55
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Toolbars
• Main Controls
• Representation Toolbar
• Common Filters
57
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – 3D View and mouse interaction
Select view orientation in the Camera Controls
Rotate
Zoom
Pan
Zoom
3D View/Canvas
58
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Fields visualization
Select Last Frame in the VCR Controls Current Time Controls
59
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Filters
• Filters are functions that generate, extract or derive features from the input data.
• They are attached to the input data.
• You can access the most commonly used filters from the Common Filters toolbar
• You can access all the filters from the menu Filter.
60
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Filters
61
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Slice filter
4. Press Apply
62
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Glyph filter
4. Color the colors using Solid Color
1. Select the Glyph filter. This
filter will be applied on the
Slice1 filter
3. Press Apply
2. Filter options
63
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Plot Over Line filter
1.a. Select the Plot Over Line
filter.
(0.5, 1, 1)
3. Press Apply
(0.5, 0, 1)
2. Enter the coordinates of the line
Line
64
Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Filters
4. Optional – Use the VCR Control to change the frame.
The line chart view will be updated automatically
1. Click on the line chart view (the blue frame indicates that it is the active view)
65
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files
• In the previous case, we ran the simulation but we did not save the standard output
stream (stdout) in a log file.
• Our advice is to always save the standard output stream (stdout) in a log file.
• It is of interest to always save the log as if something goes wrong and you would like
to do troubleshooting, you will need this information.
• Also, if you are interested in plotting the residuals you will need the log file.
• By the way, if at any point you ask us what went wrong with your simulation, it is likely
that we will ask you for this file.
66
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files
• There are many ways to save the log files.
• From now on, we will use the Linux tee command to save log files.
• To save a log file of the simulation or the output of any utility, you can proceed as
follows:
1. $> foamCleanTutorials
2. $> blockMesh | tee log.blockMesh
3. $> checkMesh | tee log.checkMesh
4. $> icoFoam | tee log.icoFoam
• You can use your favorite text editor to read the log file (e.g., gedit, vi, emacs).
67
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files
• In step 1 we erase the mesh and all the folders, except for 0, constant and system. This
script comes with your OpenFOAM® installation.
• In step 2, we generate the mesh using the meshing tool blockMesh. We also redirect the
standard output to an ascii file with the name log.blockMesh (it can be any name). The tee
command will redirect the screen output to the file log.blockMesh and at the same time will
show you the information on the screen.
• In step 3 we check the mesh quality. We also redirect the standard output to an ascii file with the
name log.checkMesh (it can be any name).
• In step 4 we run the simulation. We also redirect the standard output to an ascii file with the
name log.icoFoam (it can be any name). Remember, the tee command will redirect the
screen output to the file log.icoFoam and at the same time will show you the information on
the screen.
• To postprocess the information contained in the solver log file log.icoFoam, we can use the
utility foamLog. Type in the terminal:
• $> foamLog log.icoFoam
• This utility will extract the information inside the file log.icoFoam. The extracted information is
saved in an editable/plottable format in the directory logs.
• At this point we can use gnuplot to plot the residuals. Type in the terminal:
• $> gnuplot 68
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files
• To plot the information extracted with foamLog using gnuplot, we can proceed as
follows (remember, at this point we are using the gnuplot prompt):
1. gnuplot> set logscale y
Set log scale in the y axis
3. gnuplot> plot ‘logs/p_0’ using 1:2 with lines, ‘logs/pFinalRes_0’ using 1:2 with lines
Here we are plotting to different files. You can concatenate files using comma (,)
4. gnuplot> reset
To reset the scales
7. gnuplot> plot [30:50][] ‘logs/Ux_0’ u 1:2 w l title ‘Ux’,‘logs/Uy_0’ u 1:2 w l title ‘Uy’
Set the x range from 30 to 50 and plot tow files and set legend titles
8. gnuplot> exit
To exit gnuplot
69
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files
• The output of step 3 is the following:
• The fact that the initial residuals (red line) are dropping to the same value of the final
residuals (monotonic convergence), is a clear indication of a steady behavior.
70
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files and plotting the residuals
• It is also possible to plot the log information on the fly.
• The easiest way to do this is by using PyFoam (you will need to install it):
• $> pyFoamPlotRunner.py [options] <foamApplication>
• If you are using the lab workstations, you will need to source PyFoam. To source PyFoam, type in the
terminal:
• $> anaconda3
• If you need help or want to know all the options available,
• $> pyFoamPlotRunner.py –-help
• To run this case with pyFoamPlotRunner.py, in the terminal type:
• $> pyFoamPlotRunner.py icoFoam
• If you do not feel comfortable using pyFoamPlotRunner.py to run the solver, it is also possible to plot the
information saved in the log file using PyFoam.
• To do so you will need to use the utility pyFoamPlotWatcher.py. For example,
• $> icoFoam | tee log.icoFoam
• Then, in a new terminal window launch pyFoamPlotWatcher, as follows,
• $> pyFoamPlotWatcher.py log.icoFoam
• You can also use pyFoamPlotWatcher.py to plot the information saved in an old log file.
71
Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files and plotting the residuals
• This is a screenshot on my computer. In this case, pyFoamPlotRunner is plotting
the initial residuals and continuity errors on the fly.
72
Running my first OpenFOAM® case setup blindfold
Stopping the simulation
• Your simulation will automatically stop at the time value you set using the keyword endTime in
the controlDict dictionary.
endTime 50;
• If for any reason you want to stop your simulation before reaching the value set by the keyword
endTime, you can change this value to a number lower than the current simulation time (you
can use 0 for instance). This will stop your simulation, but it will not save your last time-step or
iteration, so be careful.
1 /*--------------------------------*- C++ -*----------------------------------*\
2 | ========= | |
3 | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
4 | \\ / O peration | Version: 8 |
5 | \\ / A nd | Web: www.OpenFOAM.org |
6 | \\/ M anipulation | |
7 \*---------------------------------------------------------------------------*/
8 FoamFile
9 {
10 version 2.0;
11 format ascii;
12 class dictionary;
13 object controlDict;
14 }
15 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
16
17 application icoFoam;
18
19 startFrom startTime;
20
21 startTime 0;
22
23 stopAt endTime;
24
25 endTime 50;
73
Running my first OpenFOAM® case setup blindfold
Stopping the simulation
• If you want to stop the simulation and save the solution, in the controlDict dictionary made
the following modification,
stopAt writeNow;
This will stop your simulation and will save the current time-step or iteration.
74
Running my first OpenFOAM® case setup blindfold
Stopping the simulation
• The previous modifications can be done on-the-fly, but you will need to set the
keyword runTimeModifiable to true in the controlDict dictionary.
• By setting the keyword runTimeModifiable to true, you will be able to modify most of
the dictionaries on-the-fly.
44
45 runTimeModifiable true;
46
75
Running my first OpenFOAM® case setup blindfold
Stopping the simulation
• You can also kill the process. For instance, if you did not launch the solver in background, go to its terminal
window and press ctrl-c. This will stop your simulation, but it will not save your last time-step or iteration, so
be careful.
• If you launched the solver in background, just identify the process id using top or htop (or any other process
manager) and terminate the associated process. Again, this will not save your last time-step or iteration.
• To identify the process id of the OpenFOAM® solver or utility, just read screen. At the beginning of the output
screen, you will find the process id number.
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 8 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
Build : 4.x-e964d879e2b3
Exec : icoFoam
Date : Mar 11 2017
Time : 23:21:50
Host : "linux-ifxc"
PID : 3100 Process id number
Case : /home/joegi/my_cases_course/5x/101OF/cavity
nProcs : 1
sigFpe : Enabling floating point exception trapping (FOAM_SIGFPE).
fileModificationChecking : Monitoring run-time modified files using timeStampMaster
allowSystemOperations : Allowing user-supplied system call operations
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
76
Running my first OpenFOAM® case setup blindfold
Stopping the simulation
• When working locally, we usually proceed in this way:
This will run the solver icoFoam (by the way, this works for any solver or utility), it will save the
standard output stream in the file log.icofoam and will show the solver output on the fly.
• If at any moment we want to stop the simulation, and we are not interested in saving the last
time-step, we press ctrl-c.
• If we are interested in saving the last time step, we modify the controlDict dictionary and
add the following keyword
stopAt writeNow;
• Remember, this modification can be done on the fly. However, you will need to set the keyword
runTimeModifiable to yes in the controlDict dictionary.
77
Running my first OpenFOAM® case setup blindfold
Cleaning the case folder
• If you want to erase the mesh and the solution in the current case folder, you can type in the
terminal,
$> foamCleanTutorials
If you are running in parallel, this will also erase the processorN directories. We will talk about
running in parallel later.
• If you are looking to only erase the mesh, you can type in the terminal,
$> foamCleanPolyMesh
• If you are only interested in erasing the saved solutions, in the terminal type,
$> foamListTimes -rm
• If you are running in parallel and you want to erase the solution saved in the processorN
directories, type in the terminal,
$> foamListTimes –rm -processor
78
Roadmap
79
A deeper view to my first OpenFOAM® case setup
• We will take a close look at what we did by looking at the case files.
• The case directory originally contains the following sub-directories: 0, constant, and
system. After running icoFoam it also contains the time step directories 1, 2, 3,
..., 48, 49, 50, the post-processing directory postProcessing, and the
log.icoFoam file (if you chose to redirect the standard output stream).
• The time step directories contain the values of all the variables at those time
steps (the solution). The 0 directory is thus the initial condition and boundary
conditions.
• The constant directory contains the mesh and dictionaries for thermophysical,
turbulence models and advanced physical models.
• The system directory contains settings for the run, discretization schemes and
solution procedures.
• The postProcessing directory contains the information related to the
functionObjects (we are going to address functionObjects later).
• The icoFoam solver reads these files and runs the case according to those
settings.
80
A deeper view to my first OpenFOAM® case setup
• Before continuing, we want to point out the following:
• Each dictionary file in the case directory has a header.
• Lines 1-7 are commented.
• You should always keep lines 8 to 14, if not, OpenFOAM® will complain.
• According to the dictionary you are using, the class keyword (line 12)
will be different. We are going to talk about this later on.
• From now on and unless it is strictly necessary, we will not show the
header when listing the dictionaries files.
81
A deeper view to my first OpenFOAM® case setup
82
A deeper view to my first OpenFOAM® case setup
The constant directory
(and by the way, open each file and go thru its content)
• In this directory you will find the sub-directory polyMesh and the dictionary file
transportProperties.
• The transportProperties file is a dictionary for the dimensioned scalar nu, or the
kinematic viscosity.
1 Mass Kilogram kg
2 Length meters m
3 Time second s
4 Temperature Kelvin K
6 Current ampere A
84
A deeper view to my first OpenFOAM® case setup
The constant directory
(and by the way, open each file and go thru its content)
17 nu nu [ 0 2 -1 0 0 0 0 ] 0.01;
[ 0 m^2 s^-1 0 0 0 0 ]
Which is equivalent to
85
A deeper view to my first OpenFOAM® case setup
The constant directory
(and by the way, open each file and go thru its content)
• In this case, as we are working with an incompressible flow, we only need to define
the kinematic viscosity.
• Later on, we will ask you to change the Reynolds number, to do so you can change
the value of nu. Remember,
• You can also change the free stream velocity U or the reference length L.
86
A deeper view to my first OpenFOAM® case setup
The constant directory
(and by the way, open each file and go thru its content)
• Depending on the physics involved and models used, you will need to define more
variables in the dictionary transportProperties.
• For instance, for a multiphase case you will need to define the density rho and
kinematic viscosity nu for each single phase. You will also need to define the surface
tension .
• Also, depending of your physical model, you will find more dictionaries in the constant
directory.
• For example, if you need to set gravity, you will need to create the dictionary g.
• If you work with compressible flows you will need to define the dynamic viscosity mu,
and many other physical properties in the dictionary thermophysicalProperties.
• As we are not dealing with compressible flows (for the moment), we are not going into
details.
87
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh directory
(and by the way, open each file and go thru its content)
• In this case, the polyMesh directory is initially empty. After generating the mesh, it
will contain the mesh in OpenFOAM® format.
• To generate the mesh in this case, we use the utility blockMesh. This utility reads
the dictionary blockMeshDict located in the system folder.
• We will briefly address a few important inputs of the blockMeshDict dictionary.
• Do not worry, we are going to revisit this dictionary during the meshing session.
• However, have in mind that rarely you will use this utility to generate a mesh for
complex geometries.
• Go to the directory system and open blockMeshDict dictionary with your favorite
text editor, we will use gedit.
88
A deeper view to my first OpenFOAM® case setup
The system/blockMeshDict dictionary
• The blockMeshDict dictionary first defines a list with a number of vertices:
• The keyword convertToMeters (line 17), is a scaling factor. In this case
17 convertToMeters 1;
18
we do not scale the dimensions.
19 xmin 0;
20 xmax 1; • In the section vertices (lines 37-58), we define the vertices coordinates of
21 ymin 0; the geometry. In this case, there are eight vertices defining the geometry.
22 ymax 1;
23 zmin 0;
OpenFOAM® always uses 3D meshes, even if the simulation is 2D.
24 zmax 1;
25 • We can directly define the vertex coordinates in the section vertices
26 xcells 20; (commented lines 49-56), or we can use macro syntax.
27 ycells 20;
28 zcells 1; • Using macro syntax we first define a variable and its value (lines 19-24),
29
37 vertices and then we can use them by adding the symbol $ to the variable name
38 ( (lines 39-46).
39 ($xmin $ymin $zmin) //vertex 0
40 ($xmax $ymin $zmin) //vertex 1 • In lines 26-28, we define a set of variables that will be used at a later time.
41 ($xmax $ymax $zmin) //vertex 2
42 ($xmin $ymax $zmin) //vertex 3 These variables are related to the number of cells in each direction.
43 ($xmin $ymin $zmax) //vertex 4
44 ($xmax $ymin $zmax) //vertex 5 • Finally, notice that the vertex numbering starts from 0 (as the counters in
45 ($xmax $ymax $zmax) //vertex 6 c++). This numbering applies for blocks as well.
46 ($xmin $ymax $zmax) //vertex 7
47
48 /*
49 (0 0 0)
50 (1 0 0)
51 (1 1 0)
52 (0 1 0)
53 (0 0 0.1)
54 (1 0 0.1)
55 (1 1 0.1)
56 (0 1 0.1)
57 */
58 );
89
A deeper view to my first OpenFOAM® case setup
The system/blockMeshDict dictionary
• The blockMeshDict dictionary also defines the boundary patches:
• To sum up, the blockMeshDict dictionary generates in this case a single block with:
• X/Y/Z dimensions: 1.0/1.0/1.0
• Cells in the X, Y and Z directions: 20 x 20 x 1 cells.
• One single hex block with straight lines.
• Patch type wall and patch name fixedWalls at three sides.
• Patch type wall and patch name movingWall at one side.
• Patch type empty and patch name frontAndBack patch at two sides.
• If you are interested in visualizing the actual block topology, you can use paraFoam
as follows,
• $> paraFoam –block
91
A deeper view to my first OpenFOAM® case setup
The system/blockMeshDict dictionary
92
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
• First of all, this file is automatically generated after you create the mesh
using blockMesh or snappyHexMesh, or when you convert the mesh from
a third-party format.
• In this file, the geometrical information related to the base type patch of
each boundary (or surface patch) of the domain is specified.
• The base type boundary condition is the actual surface patch where we are
going to apply a numerical type boundary condition (or numerical boundary
condition).
• The numerical type boundary condition assign a field value to the surface
patch (base type).
• We define the numerical type patch (or the value of the boundary
condition), in the directory 0 or time directories.
93
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
fixedWall
fixedWall
34 frontAndBack
35 {
36 type empty;
37 inGroups 1(empty);
38 nFaces 800;
39 startFace 840;
40 }
41 )
frontAndBack
fixedWall
94
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
18 3
19 ( Name and type of the surface patches
20 movingWall Name
21 {
22 type wall; Type • The name and type of the patch is given by
23 inGroups 1(wall);
24 nFaces 20; the user.
25 startFace 760;
26 } • In this case the name and type was assigned
27 fixedWalls in the dictionary blockMeshDict.
28 {
29 type wall; • You can change the name if you do not like it.
30 inGroups 1(wall);
31 nFaces 60; Do not use strange symbols or white spaces.
32 startFace 780;
33 } • You can also change the base type. For
34 frontAndBack instance, you can change the type of the
35 {
36 type empty;
patch movingWall from wall to patch.
37 inGroups 1(empty);
38 nFaces 800;
• When converting the mesh from a third party
39 startFace 840; format, OpenFOAM® will try to recover the
40 } information from the original format. But it
41 )
might happen that it does not recognizes the
base type and name of the original file. In this
case you will need to modify this file manually.
95
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
18 3 inGroups keyword
19 ( • This keyword is optional. You can erase this information safely.
20 movingWall
21 { • It is used to group patches during visualization in
22 type wall; ParaView/paraFoam. If you open this mesh in paraFoam you will
23 inGroups 1(wall); see that there are two groups, namely: wall and empty.
24 nFaces 20;
25 startFace 760; • As usual, you can change the name.
26 } • If you want to put a surface patch in two groups, you can proceed
27 fixedWalls
as follows:
28 {
29 type wall; 2(wall wall1)
30 inGroups 1(wall);
31 nFaces 60;
In this case the surface patch belongs to the groups wall and
32 startFace 780; wall1.
33 } • Groups can have more than one patch.
34 frontAndBack
35 {
36 type empty; nFaces and startFace keywords
37 inGroups 1(empty);
38 nFaces 800; • Unless you know what you are doing, you do not need to
39 startFace 840; modify this information.
40 }
41 ) • This information is related to the starting face and ending face of
the boundary patch in the mesh data structure.
• This information is created automatically when generating the
mesh or converting the mesh.
96
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
• There are a few base type patches that are constrained or paired. This means that the type
should be the same in the boundary file and in the numerical boundary condition defined in the
field files, e.g., the files 0/U and 0/p.
• In this case, the base type of the patch frontAndBack (defined in the file boundary), is
consistent with the numerical type patch defined in the field files 0/U and 0/p. They are of
the type empty.
• Also, the base type of the patches movingWall and fixedWalls (defined in the file boundary),
is consistent with the numerical type patch defined in the field files 0/U and 0/p.
• This is extremely important, especially if you are converting meshes as not always the type of
the patches is set as you would like.
• Hence, it is highly advisable to do a sanity check and verify that the base type of the patches
(the type defined in the file boundary), is consistent with the numerical type of the patches
(the patch type defined in the field files contained in the directory 0 (or whatever time directory
you defined the boundary and initial conditions).
• If the base type and numerical type boundary conditions are not consistent, OpenFOAM® will
complain.
• Do not worry, we are going to address boundary conditions later on.
97
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
symmetry symmetry
symmetryPlane symmetryPlane
empty empty
wedge wedge
cyclic cyclic
processor processor
98
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
• The base type patch can be any of the numerical or derived type
boundary conditions available in OpenFOAM®. Mathematically speaking;
they can be Dirichlet, Neumann or Robin boundary conditions.
fixedValue
zeroGradient
inletOutlet
slip
patch
totalPressure
supersonicFreeStream
and so on …
Refer to the doxygen documentation for a list of all numerical
type boundary conditions available.
99
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
type fixedValue;
wall zeroGradient
value uniform (U V W);
• This boundary condition is not contained in the patch base type boundary
condition group, because specialize modeling options can be used on this
boundary condition.
• An example is turbulence modeling, where turbulence can be generated or
dissipated at the walls.
100
A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary
• The name of the base type boundary condition and the name of the
numerical type boundary condition needs to be the same, if not,
OpenFOAM® will complain.
• Pay attention to this, specially if you are converting the mesh from another
format.
• As you can see, all the names are the same across all the dictionary files.
101
A deeper view to my first OpenFOAM® case setup
The system directory
(and by the way, open each file and go thru its content)
103
A deeper view to my first OpenFOAM® case setup
The controlDict dictionary
• So how do we know what options are available for each keyword?
• The hard way is to refer to the source code.
• The easy way is to use the banana method.
17 application icoFoam;
18 • So what is the banana method? This method consist in inserting a dummy word
19 startFrom startTime;
20
(that does not exist in the installation) and let OpenFOAM® list the available
21 startTime 0; options.
22
23 stopAt banana; • For example. If you add banana in line 23, you will get this output:
24
25 endTime 50;
banana is not in enumeration
26 4
27 deltaT 0.01;
28 (
29 writeControl runTime;
30 nextWrite
31 writeInterval 1;
32 writeNow
33 purgeWrite 0;
34
noWriteNow
35 writeFormat ascii; endTime
36
37 writePrecision 8; )
38
39 writeCompression off; • So your options are nextWrite, writeNow, noWriteNow, endTime
40
41 timeFormat general; • And how do we know that banana does not exist in the source code? Just type in
42 the terminal:
43 timePrecision 6;
44 • $> src
45 runTimeModifiable true;
• $> grep –r –n banana .
• If you see some bananas in your output someone is messing around with your
installation.
• Remember, you can use any dummy word, but you have to be sure that it does
not exist in OpenFOAM®.
104
A deeper view to my first OpenFOAM® case setup
The controlDict dictionary
105
A deeper view to my first OpenFOAM® case setup
The fvSchemes dictionary
17 solvers
• To solve U we are using the smoothSolver method, with the
18 { smoother symGaussSeidel, an absolute tolerance equal to
19 p
20 { 1e-08 and a relative tolerance relTol equal to 0.
21 solver PCG;
22 preconditioner DIC; • The solvers will iterative until reaching any of the tolerance
23 tolerance 1e-06;
24 relTol 0; values set by the user or reaching a maximum value of
39 }
iterations (optional entry).
40
41 pFinal • FYI, solving for the velocity is relative inexpensive, whereas
42
43
{
$p;
solving for the pressure is expensive.
44 relTol 0;
45 } • The PISO sub-dictionary contains entries related to the
46
47 U
pressure-velocity coupling method (the PISO method).
48 {
49 solver smoothSolver; • In this case we are doing only one PISO correction and no
50 smoother symGaussSeidel;
51 tolerance 1e-08;
orthogonal corrections.
52 relTol 0;
53 } • You need to do at least one PISO loop (nCorrectors).
54 }
55
56 PISO
57 {
58 nCorrectors 1;
59 nNonOrthogonalCorrectors 0;
60 pRefCell 0;
61 pRefValue 0;
62 }
108
A deeper view to my first OpenFOAM® case setup
The system directory
(optional dictionary files)
• In the system directory you will also find these two additional files:
• decomposeParDict
• sampleDict
109
A deeper view to my first OpenFOAM® case setup
The sampleDict dictionary
Type of sampling, sets will sample along a line.
Format of the output file, raw format is a generic format
17 type sets; that can be read by many applications. The output file is
18
19 setFormat raw;
human readable (ascii format).
20
23 interpolationScheme cellPointFace; Interpolation method at the solution level (location of the
24
26 fields interpolation points).
27 (
28 U Fields to sample.
29 );
30
31 sets
32 (
33 Sample method. How to interpolate the solution to the
34
35
l1
{
sample entity (line in this case)
38 type lineFace;
43 axis x;
44 start ( -1 0.5 0); Location of the sample line. We define start and end
45
46 }
end ( 2 0.5 0); point, and the axis of the sampling.
47
48 l2
49 {
52
57
type
axis
lineFace;
y;
Sample method from the solution to the line.
58 start (0.5 -1 0);
59 end (0.5 2 0);
60 }
61
62 );
Location of the sample line. We define start and end
point, and the axis of the sampling.
110
A deeper view to my first OpenFOAM® case setup
The sampleDict dictionary
• The 0 directory contains the initial and boundary conditions for all primitive variables,
in this case p and U. The U file contains the following information (velocity vector):
112
A deeper view to my first OpenFOAM® case setup
The 0 directory
(and by the way, open each file and go thru its content)
• The 0 directory contains the initial and boundary conditions for all primitive variables,
in this case p and U. The U file contains the following information (velocity):
• The 0 directory contains the initial and boundary conditions for all primitive variables,
in this case p and U. The p file contains the following information (modified pressure):
114
A deeper view to my first OpenFOAM® case setup
The 0 directory
(and by the way, open each file and go thru its content)
• The 0 directory contains the initial and boundary conditions for all primitive variables,
in this case p and U. The p file contains the following information (modified pressure):
115
A deeper view to my first OpenFOAM® case setup
with units
116
A deeper view to my first OpenFOAM® case setup
• Coming back to the headers, and specifically the headers related to the field variable
dictionaries (e.g. U, p, gradU, and so on).
• In the header of the field variables, the class type should be consistent with the type
of field variable you are using.
• Be careful with this, specially if you are copying and pasting files.
• If the field variable is a scalar, the class should be volScalarField.
117
A deeper view to my first OpenFOAM® case setup
• If the field variable is a vector, the class should be volVectorField.
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 8 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
object U;
}
• If the field variable is a tensor (e.g. the velocity gradient tensor), the class should be
volTensorField.
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 8 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volTensorField;
object gradU;
} 118
A deeper view to my first OpenFOAM® case setup
The output screen
• Finally, let us talk about the output screen, which shows a lot of information.
Velocity residuals
Simulation time
Courant number
Pressure residuals
No orthogonal corrections
Only one PISO correction
Execution time (wall time)
Continuity errors
Additional information
End of the simulation Minimum and maximum values of each field
119
A deeper view to my first OpenFOAM® case setup
The output screen
• By default, OpenFOAM® does not show the minimum and maximum information. To print out this information,
we use functionObjects. We are going to address functionObjects in detail when we deal with post-
processing and sampling.
• But for the moment, what we need to know is that we add functionObjects at the end of the controlDict
dictionary. In this case, we are using a functionObject that prints the minimum and maximum information of
the selected fields.
• This information complements the residuals information and it is saved in the postProcessing directory. It
gives a better indication of stability, boundedness and consistency of the solution.
49 functions
50 {
51 Name of the folder where the output of
52 /////////////////////////////////////////////////////////////////////////// the functionObject will be saved
53
54 minmaxdomain
55 {
56 type fieldMinMax; functionObject to use
57
58 functionObjectLibs ("libfieldFunctionObjects.so");
59
60 enabled true; //true or false Turn on/off functionObject
61
62 mode component;
63
64 writeControl timeStep;
65 writeInterval 1; Output interval of functionObject
66
67 log true; Save output of the functionObject in a ascii file
68
69 fields (p U); Field variables to sample
70 }
91
92 };
120
A deeper view to my first OpenFOAM® case setup
The output screen
• Another very important output information is the CFL or Courant number.
• The Courant number imposes the CFL number condition, which is the maximum allowable
CFL number a numerical scheme can use. For the n - dimensional case, the CFL number
condition becomes,
• In OpenFOAM®, most of the solvers are implicit, which means they are unconditionally
stable. In other words, they are not constrained to the CFL number condition.
• However, the fact that you are using a numerical method that is unconditionally stable, does
not mean that you can choose a time step of any size.
• The time-step must be chosen in such a way that it resolves the time-dependent features, and it
maintains the solver stability.
• For the moment and for the sake of simplicity, let us try to keep the CFL number below 5.0 and
preferably close to 1.0 (for good accuracy).
• Other properties of the numerical method that you should observe are: conservationess,
boundedness, transportiveness, and accuracy. We are going to address these properties and
the CFL number when we deal with the FVM theory. 121
A deeper view to my first OpenFOAM® case setup
The output screen
• To control the CFL number you can change the time step or you can change the mesh.
• The easiest way is by changing the time step.
• For a time step of 0.01 seconds, this is the output you should get for this case,
Time = 49.99
CFL number at
Courant Number mean: 0.044365026 max: 0.16800273
time step n - 1
smoothSolver: Solving for Ux, Initial residual = 1.1174405e-09, Final residual = 1.1174405e-09, No Iterations 0
smoothSolver: Solving for Uy, Initial residual = 1.4904251e-09, Final residual = 1.4904251e-09, No Iterations 0
DICPCG: Solving for p, Initial residual = 6.7291723e-07, Final residual = 6.7291723e-07, No Iterations 0
time step continuity errors : sum local = 2.5096865e-10, global = -1.7872395e-19, cumulative = 2.6884327e-18
ExecutionTime = 4.47 s ClockTime = 5 s
Time = 50
CFL number at
Courant Number mean: 0.044365026 max: 0.16800273
smoothSolver: Solving for Ux, Initial residual = 1.0907508e-09, Final residual = 1.0907508e-09, No Iterations 0 time step n
smoothSolver: Solving for Uy, Initial residual = 1.4677462e-09, Final residual = 1.4677462e-09, No Iterations 0
DICPCG: Solving for p, Initial residual = 1.0020944e-06, Final residual = 1.0746895e-07, No Iterations 1
time step continuity errors : sum local = 4.0107145e-11, global = -5.0601748e-20, cumulative = 2.637831e-18
ExecutionTime = 4.47 s ClockTime = 5 s
122
A deeper view to my first OpenFOAM® case setup
The output screen
• To control the CFL number you can change the time step or you can change the mesh.
• The easiest way is by changing the time step.
• For a time step of 0.1 seconds, this is the output you should get for this case,
Time = 49.9
CFL number at
Courant Number mean: 0.4441161 max: 1.6798756
time step n - 1
smoothSolver: Solving for Ux, Initial residual = 0.00016535808, Final residual = 2.7960145e-09, No Iterations 5
smoothSolver: Solving for Uy, Initial residual = 0.00015920267, Final residual = 2.7704949e-09, No Iterations 5
DICPCG: Solving for p, Initial residual = 0.0015842846, Final residual = 5.2788554e-07, No Iterations 26
time step continuity errors : sum local = 8.6128916e-09, global = 3.5439859e-19, cumulative = 2.4940081e-17
ExecutionTime = 0.81 s ClockTime = 1 s
Time = 50
CFL number at
Courant Number mean: 0.44411473 max: 1.6798833
smoothSolver: Solving for Ux, Initial residual = 0.00016378098, Final residual = 2.7690608e-09, No Iterations 5 time step n
smoothSolver: Solving for Uy, Initial residual = 0.00015720331, Final residual = 2.7354499e-09, No Iterations 5
DICPCG: Solving for p, Initial residual = 0.0015662416, Final residual = 5.2290439e-07, No Iterations 26
time step continuity errors : sum local = 8.5379223e-09, global = -3.6676527e-19, cumulative = 2.4573316e-17
ExecutionTime = 0.81 s ClockTime = 1 s
123
A deeper view to my first OpenFOAM® case setup
The output screen
• To control the CFL number you can change the time step or you can change the mesh.
• The easiest way is by changing the time step.
• For a time step of 0.5 seconds, this is the output you should get for this case,
Time = 2
CFL number at
Courant Number mean: 1.6828931 max: 5.6061178
time step n - 1
smoothSolver: Solving for Ux, Initial residual = 0.96587058, Final residual = 4.9900041e-09, No Iterations 27
smoothSolver: Solving for Uy, Initial residual = 0.88080685, Final residual = 9.7837781e-09, No Iterations 25
DICPCG: Solving for p, Initial residual = 0.95568243, Final residual = 7.9266324e-07, No Iterations 33
time step continuity errors : sum local = 6.3955627e-06, global = 1.3227253e-17, cumulative = 1.4125109e-17
ExecutionTime = 0.04 s ClockTime = 0 s
124
A deeper view to my first OpenFOAM® case setup
The output screen
• Another output you should monitor are the continuity errors.
• These numbers should be small (it does not matter if they are negative or positive).
• If these values increase in time (about the order of 1e-2), you better control the case setup because
something is wrong.
• The continuity errors are defined in the following file
$WM_PROJECT_DIR/src/finiteVolume/cfdTools/incompressible/continuityErrs.H
Time = 50
125
A deeper view to my first OpenFOAM® case setup
Error output
• If you forget a keyword or a dictionary file, give a wrong option to a compulsory or optional entry,
misspelled something, add something out of place in a dictionary, use the wrong dimensions,
forget a semi-colon and so on, OpenFOAM® will give you the error FOAM FATAL IO ERROR.
• This error does not mean that the actual OpenFOAM® installation is corrupted. It is telling you
that you are missing something or something is wrong in a dictionary.
• Maybe the guys of OpenFOAM® went a little bit extreme here.
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 8 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
Build : 5.x-5d8318b22cbe
Exec : icoFoam
Date : Nov 02 2014
Time : 00:33:41
Host : "linux-cfd"
PID : 3675
Case : /home/cfd/my_cases_course/cavity
nProcs : 1
sigFpe : Enabling floating point exception trapping (FOAM_SIGFPE).
fileModificationChecking : Monitoring run-time modified files using timeStampMaster
allowSystemOperations : Allowing user-supplied system call operations
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Create time
126
A deeper view to my first OpenFOAM® case setup
Error output
• Also, before entering into panic read carefully the output screen because OpenFOAM® is telling
you what is the error and how to correct it.
Build : 6.x-5d8318b22cbe
Exec : icoFoam
Date : Nov 02 2014
Time : 00:33:41
Host : "linux-cfd"
PID : 3675
Case : /home/cfd/my_cases_course/cavity
nProcs : 1
sigFpe : Enabling floating point exception trapping (FOAM_SIGFPE).
fileModificationChecking : Monitoring run-time modified files using timeStampMaster
allowSystemOperations : Allowing user-supplied system call operations
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Create time
FOAM exiting
127
A deeper view to my first OpenFOAM® case setup
Error output
• It is very important to read the screen and understand the output.
• Train yourself to identify the errors. Hereafter we list a few possible errors.
• Missing compulsory file p
FOAM exiting
128
A deeper view to my first OpenFOAM® case setup
Error output
• Mismatching patch name in file p
FOAM exiting
FOAM exiting
129
A deeper view to my first OpenFOAM® case setup
Error output
• Missing entry in file fvSolution at keyword PISO
--> FOAM FATAL IO ERROR:
"ill defined primitiveEntry starting at keyword 'PISO' on line 68 and ending at line 68"
FOAM exiting
FOAM aborting
#0 Foam::error::printStack(Foam::Ostream&) at ??:?
#1 Foam::error::abort() at ??:?
#2 void Foam::checkMethod<Foam::Vector<double> >(Foam::fvMatrix<Foam::Vector<double> > const&,
Foam::fvMatrix<Foam::Vector<double> > const&, char const*) at ??:?
#3 ? at ??:?
#4 ? at ??:?
#5 __libc_start_main in "/lib64/libc.so.6"
#6 ? at /home/abuild/rpmbuild/BUILD/glibc-2.19/csu/../sysdeps/x86_64/start.S:125
Aborted 130
A deeper view to my first OpenFOAM® case setup
Error output
• Missing keyword deltaT in file controlDict
FOAM exiting
• Missing file points in directory polyMesh. Likely you are missing the mesh.
From function Time::findInstance(const fileName&, const word&, const IOobject::readOption, const word&)
in file db/Time/findInstance.C at line 203.
FOAM exiting
131
A deeper view to my first OpenFOAM® case setup
Error output
• Unknown boundary condition type.
74
(
SRFFreestreamVelocity
SRFVelocity
SRFWallVelocity
activeBaffleVelocity
...
...
...
variableHeightFlowRateInletVelocity
waveTransmissive
wedge
zeroGradient
)
FOAM exiting
132
A deeper view to my first OpenFOAM® case setup
Error output
• This one is especially hard to spot
/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 8 |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
Build : 6.x-5d8318b22cbe
Exec : icoFoam
Date : Nov 02 2014
Time : 00:33:41
Host : "linux-cfd"
PID : 3675
fileName::stripInvalid() called for invalid fileName /home/cfd/my_cases_course/cavity0
For debug level (= 2) > 1 this is considerd fatal
Aborted
• This error is related to the name of the working directory. In this case the name of the
working directory is cavity 0 (there is a blank space between the word cavity and
the number 0).
• Do not use blank spaces or funny symbols when naming directories and files.
• Instead of cavity 0 you could use cavity_0.
133
A deeper view to my first OpenFOAM® case setup
Error output
• You should worry about the SIGFPE error signal. This error signal indicates that something
went really wrong (erroneous arithmetic operation).
• This message (that seems a little bit difficult to understand), is giving you a lot information.
• For instance, this output is telling us that the error is due to SIGFPE and the class associated to
the error is lduMatrix. It is also telling you that the GAMGSolver solver is the affected one
(likely the offender is the pressure).
#0 Foam::error::printStack(Foam::Ostream&) at ??:?
#1 Foam::sigFpe::sigHandler(int) at ??:?
#2 in "/lib64/libc.so.6"
#3 Foam::DICPreconditioner::calcReciprocalD(Foam::Field<double>&, Foam::lduMatrix const&) at ??:?
#4 Foam::DICSmoother::DICSmoother(Foam::word const&, Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double>
const&, Foam::FieldField<Foam::Field, double> const&, Foam::UPtrList<Foam::lduInterfaceField const> const&) at ??:?
#5 Foam::lduMatrix::smoother::addsymMatrixConstructorToTable<Foam::DICSmoother>::New(Foam::word const&,
Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double> const&, Foam::FieldField<Foam::Field, double> const&,
Foam::UPtrList<Foam::lduInterfaceField const> const&) at ??:?
#6 Foam::lduMatrix::smoother::New(Foam::word const&, Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double>
const&, Foam::FieldField<Foam::Field, double> const&, Foam::UPtrList<Foam::lduInterfaceField const> const&,
Foam::dictionary const&) at ??:?
#7 Foam::GAMGSolver::initVcycle(Foam::PtrList<Foam::Field<double> >&, Foam::PtrList<Foam::Field<double> >&,
Foam::PtrList<Foam::lduMatrix::smoother>&, Foam::Field<double>&, Foam::Field<double>&) const at ??:?
#8 Foam::GAMGSolver::solve(Foam::Field<double>&, Foam::Field<double> const&, unsigned char) const at ??:?
#9 Foam::fvMatrix<double>::solveSegregated(Foam::dictionary const&) at ??:?
#10 Foam::fvMatrix<double>::solve(Foam::dictionary const&) at ??:?
#11
at ??:?
#12 __libc_start_main in "/lib64/libc.so.6"
#13
at /home/abuild/rpmbuild/BUILD/glibc-2.17/csu/../sysdeps/x86_64/start.S:126
Floating point exception 134
A deeper view to my first OpenFOAM® case setup
Dictionary files general features
/*
// This is a line comment This is a block comment
*/
• As in C++, you can use the #include directive in your dictionaries (do not forget to create the respective include file):
#include “ n t C nd t n ”
135
A deeper view to my first OpenFOAM® case setup
Dictionary files general features
U Sub-dictionary U
{
solver PBiCGStab;
preconditioner DILU;
tolerance 1e-06;
relTol 0;
}
…
…
…
} 137
A deeper view to my first OpenFOAM® case setup
Dictionary files general features
• Macro expansion.
• We first declare a variable (x = 10) and then we use it through the $ macro substitution ($x).
type fixedValue;
value uniform $scalarField; //Use declared variable
• You can use macro expansion to duplicate and access variables in dictionaries
“( eft|r ght|t )W ”
{
type fixedValue;
value uniform (0 0 0);
}
“.*W ”
{
type fixedValue;
value uniform (0 0 0);
}
• Inline calculations.
• You can use the directive #calc to do inline calculations, the syntax is as follows:
X = 10.0; //Declare variable
Y = 3.0; //Declare variable
• With inline calculations you can access all the mathematical functions available in C++.
• Macro expansions and inline calculations are very useful to parametrize dictionaries and avoid repetitive tasks.
• Switches: they are used to enable or disable a function or a feature in the dictionaries.
• Switches are logical values. You can use the following values:
Switches
false true
off on
no yes
n y
f t
none true
• You can find all the valid switches in the following file:
OpenFOAM-6/src/OpenFOAM/primitives/bools/Switch/Switch.C 140
A deeper view to my first OpenFOAM® case setup
Solvers and utilities help
• If you need help about a solver or utility, you can use the option –help. For
instance:
will print some basic help and usage information about icoFoam
• Remember, you have the source code there so you can always
check the original source.
141
A deeper view to my first OpenFOAM® case setup
Solvers and utilities help
• To get more information about the boundary conditions, post-processing utilities, and the API read the
Doxygen documentation.
• If you did not compile the Doxygen documentation, you can access the information online,
http://cpp.openfoam.org/v6/
API documentation
142
A deeper view to my first OpenFOAM® case setup
Exercises
• Run the case with Re = 10 and Re = 1000. Feel free to change any variable to achieve the Re value (velocity,
viscosity or length). Do you see an unsteady behavior in any of the cases? What about the computing time,
what simulation is faster?
• Run the tutorial with Re = 100, a mesh with 120 x 120 x 1 cells, and using the default setup (original
controlDict, fvSchemes and fvSolution). Did the simulation converge? Did it crash? Any comments.
• If your simulation crashed, try to solve the problem.
(Hint: try to reduce the time-step to get a CFL less than 1)
• Besides reducing the time-step, can you find another solution?
(Hint: look at the PISO options)
• Change the base type of the boundary patch movingWall to patch. (the boundary file). Do you get the same
results? Can you comment on this?
• Try to extent the problem to 3D and use a uniform mesh (20 x 20 x 20). Compare the solution at the mid
section of the 3D simulation with the 2D solution. Are the solutions similar?
• How many time discretization schemes are there in OpenFOAM®? Try to use a different discretization
scheme.
• Run the simulation using Gauss upwind instead of Gauss linear for the term div(phi,U) (fvSchemes). Do
you get the same quantitative results?
• Sample the field variables U and P at a different location and plot the results using gnuplot.
• What density value do you think we were using? What about dynamic viscosity?
Hint: the physical pressure is equal to the modified pressure and 143
Roadmap
144
3D Dam break – Free surface flow
blockMesh
+
snappyHexMesh
setFields
interFoam functionObjects
sampling paraview
146
3D Dam break – Free surface flow
At the end of the day, you should get something like this
147
3D Dam break – Free surface flow
148
3D Dam break – Free surface flow
$PTOFC/101OF/3d_damBreak
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
149
3D Dam break – Free surface flow
150
3D Dam break – Free surface flow
The constant directory
• g
• transportProperties
• momentumTransport
151
3D Dam break – Free surface flow
The g dictionary file
152
3D Dam break – Free surface flow
The transportProperties dictionary file
Primary phase
153
3D Dam break – Free surface flow
The momentumTransport dictionary file
• In this dictionary file we select what model we would like to use (laminar or
turbulent).
• This dictionary is compulsory.
• In this case we use a RANS turbulence model (kEpsilon).
17 simulationType RAS;
18
19 RAS
20 {
21 RASModel kEpsilon;
22
23 turbulence on;
24
25 printCoeffs on;
26 }
154
3D Dam break – Free surface flow
The 0 directory
• In this directory, we will find the dictionary files that contain the boundary and
initial conditions for all the primitive variables.
• As we are solving the incompressible RANS Navier-Stokes equations using
the VOF method, we will find the following field files:
155
3D Dam break – Free surface flow
The file 0/alpha.water
17 dimensions [0 0 0 0 0 0 0];
18 • This file contains the boundary and initial conditions
19
20
internalField uniform 0; for the non-dimensional scalar field alpha.water
21 boundaryField
22 { • This file is named alpha.water, because the
23
24
front
{
primary phase is water (we defined the primary
25 type zeroGradient; phase in the transportProperties dictionary).
26 }
27
28
back
{
• Initially, this field is initialized as 0 in the whole
29 type zeroGradient; domain (line 19). This means that there is no water in
30 }
31 left the domain at time 0. Later, we will initialize the
32
33
{
type zeroGradient;
water column and this file will be overwritten with a
34 } non-uniform field for the internalField.
35 right
36
37
{
type zeroGradient;
• For the front, back, left, right, bottom and
38 } stlSurface patches we are using a zeroGradient
39 bottom
40 { boundary condition (we are just extrapolating the
41 type zeroGradient; internal values to the boundary face).
42 }
43 top
44 { • For the top patch we are using an inletOutlet
45
46
type
inletValue
inletOutlet;
uniform 0;
boundary condition. This boundary condition avoids
47 value uniform 0; backflow into the domain. If the flow is going out it
48 }
49 stlSurface will use zeroGradient and if the flow is coming back
50 { it will assign the value set in the keyword inletValue
51 type zeroGradient;
52 } (line 46).
53
54 }
156
3D Dam break – Free surface flow
The file 0/p_rgh
17 dimensions [1 -1 -2 0 0 0 0];
18 • This file contains the boundary and initial conditions
19 internalField uniform 0;
20 for the dimensional scalar field p_rgh. The
21
22
boundaryField
{
dimensions of this field are given in Pascal (line 17)
23 front
24 { • This scalar field contains the value of the static
25
26
type
value
fixedFluxPressure;
uniform 0;
pressure field minus the hydrostatic component.
27 }
28 back • This field is initialized as 0 in the whole domain (line
33 left
19).
38 right • For the front, back, left, right, bottom and
43 bottom
stlSurface patches we are using the
fixedFluxPressure boundary condition (refer to the
48 top
49 { source code or doxygen documentation to know
50
51
type
p0
totalPressure;
uniform 0;
more about this boundary condition).
52 U U;
53 phi phi; • For the top patch we are using the totalPressure
54
55
rho
psi
rho;
none;
boundary condition (refer to the source code or
56 gamma 1; doxygen documentation to know more about this
57 value uniform 0;
58 } boundary condition).
59 stlSurface
60 {
61 type fixedFluxPressure;
62 value uniform 0;
63 }
64
65 }
157
3D Dam break – Free surface flow
The file 0/U
17 dimensions [0 -1 -1 0 0 0 0];
18 • This file contains the boundary and initial conditions
19 internalField uniform (0 0 0);
20 for the dimensional vector field U.
21 boundaryField
22 { • We are using uniform initial conditions and the
23 front
24 { numerical value is (0 0 0) (keyword internalField in
25
26
type
value
fixedValue;
uniform (0 0 0);
line 19).
27 }
28 back • The front, back, left, right, bottom and stlSurface
33 left
patches are no-slip walls, therefore we impose a
fixedValue boundary condition with a value of (0 0 0)
38 right
at the wall.
43 bottom
• For the top patch we are using the
48 top
49 { pressureInlterOutletVelocity boundary condition
50
51
type
value
pressureInletOutletVelocity;
uniform (0 0 0);
(refer to the source code or doxygen documentation
52 } to know more about this boundary condition).
53 stlSurface
54 {
55 type fixedValue;
56 value uniform (0 0 0);
57 }
58
59 }
158
3D Dam break – Free surface flow
The file 0/k
17 dimensions [0 2 -2 0 0 0 0];
18 • This file contains the boundary and initial conditions
19 internalField uniform 0.1;
20 for the dimensional scalar field k.
21 boundaryField
22 { • This scalar (turbulent kinetic energy), is related to the
23 “(front|back|left|right|bottom|stlSurface)”
24 { turbulence model.
25 type kqRWallFunction;
26 value $internalField; • This field is initialized as 0.1 in the whole domain,
27 }
28 and all the boundary patches take the same value
29
30
top
{
($internalField).
31 type inletOutlet;
32 inletValue $internalField; • For the front, back, left, right, bottom and
33
34 }
value $internalField;
stlSurface patches we are using the
35 kqRWallFunction boundary condition, which applies
36 }
a wall function at the walls (refer to the source code
or doxygen documentation to know more about this
boundary condition).
• For the top patch we are using the inletOutlet
boundary condition, this boundary condition handles
backflow (refer to the source code or doxygen
documentation to know more about this boundary
condition).
• We will deal with turbulence modeling later.
159
3D Dam break – Free surface flow
The file 0/epsilon
17 dimensions [0 2 -3 0 0 0 0];
18 • This file contains the boundary and initial conditions
19 internalField uniform 0.1;
20 for the dimensional scalar field epsilon.
21 boundaryField
22 { • This scalar (rate of dissipation of turbulence energy),
23 “(front|back|left|right|bottom|stlSurface)”
24 { is related to the turbulence model.
25 type epsilonWallFunction;
26 value $internalField; • This field is initialized as 0.1 in the whole domain,
27 }
28 and all the boundary patches take the same value
29
30
top
{
($internalField).
31 type inletOutlet;
32 inletValue $internalField; • For the front, back, left, right, bottom and
33
34 }
value $internalField;
stlSurface patches we are using the
35 epsilonWallFunction boundary condition, which
36 }
applies a wall function at the walls (refer to the
source code or doxygen documentation to know
more about this boundary condition).
• For the top patch we are using the inletOutlet
boundary condition, this boundary condition handles
backflow (refer to the source code or doxygen
documentation to know more about this boundary
condition).
• We will deal with turbulence modeling later.
160
3D Dam break – Free surface flow
The file 0/nut
17 dimensions [0 2 -1 0 0 0 0];
18 • This file contains the boundary and initial conditions
19 internalField uniform 0;
20 for the dimensional scalar field nut.
21 boundaryField
22 { • This scalar (turbulent viscosity), is related to the
23 “(front|back|left|right|bottom|stlSurface)”
24 { turbulence model.
25 type nutkWallFunction;
26 value $internalField; • This field is initialized as 0 in the whole domain, and
27 }
28 all the boundary patches take the same value
29
30
top
{
($internalField).
31 type calculated;
32 value $internalField;; • For the front, back, left, right, bottom and
33
34
}
stlSurface patches we are using the
35 } nutkWallFunction boundary condition, which applies
a wall function at the walls (refer to the source code
or doxygen documentation to know more about this
boundary condition).
• For the top patch we are using the calculated
boundary condition, this boundary condition
computes the value of nut from k and epsilon (refer to
the source code or doxygen documentation to know
more about this boundary condition).
• We will deal with turbulence modeling later.
161
3D Dam break – Free surface flow
The system directory
162
3D Dam break – Free surface flow
The controlDict dictionary
• This case starts from time 0 (startTime), and it will run up to 8
17 application interFoam; seconds (endTime).
18
19
20
startFrom startTime;
• The initial time step of the simulation is 0.0001 seconds
21 startTime 0; (deltaT).
22
23
24
stopAt endTime;
• It will write the solution every 0.02 seconds (writeInterval) of
25 endTime 8; simulation time (runTime). It will automatically adjust the time
26
27 deltaT 0.0001; step (adjustableRunTime), in order to save the solution at the
28
29 writeControl adjustableRunTime;
precise write interval.
30
31 writeInterval 0.02; • It will keep all the solution directories (purgeWrite).
32
33 purgeWrite 0; • It will save the solution in ascii format (writeFormat).
34
35 writeFormat ascii;
36 • The write precision is 8 digits (writePrecision). It will only save
37
38
writePrecision 8; eight digits in the output files.
39 writeCompression uncompressed;
40 • And as the option runTimeModifiable is on, we can modify all
41
42
timeFormat general; these entries while we are running the simulation.
43 timePrecision 8;
44 • In line 47 we turn on the option adjustTimeStep. This option
45
46
runTimeModifiable yes;
will automatically adjust the time step to achieve the maximum
47 adjustTimeStep yes; desired courant number (lines 49-50). We also set a maximum
48
49 maxCo 1.0; time step in line 51.
50 maxAlphaCo 0.5;
51 maxDeltaT 0.01; • Remember, the first time step of the simulation is done using
the value set in line 27 and then it is automatically scaled to
achieve the desired maximum values (lines 49-51).
163
3D Dam break – Free surface flow
The controlDict dictionary
144 };
164
3D Dam break – Free surface flow
The controlDict dictionary
144 };
165
3D Dam break – Free surface flow
The controlDict dictionary
144 };
Sampling locations
(probeLocations)
166
3D Dam break – Free surface flow
The controlDict dictionary
167
3D Dam break – Free surface flow
The fvSchemes dictionary
17 ddtSchemes • In this case, for time discretization (ddtSchemes) we are using the
18 {
19 default Euler; Euler method.
21 }
22
• For gradient discretization (gradSchemes) we are using the Gauss
23 gradSchemes linear as the default method and slope limiters (cellLimited) for the
24 { velocity gradient or grad(U).
25 default Gauss linear;
26 grad(U) cellLimited Gauss linear 1; • For the discretization of the convective terms (divSchemes) we are
27 }
28
using linearUpwindV interpolation method for the term
29 divSchemes div(rhoPhi,U).
30 {
31 div(rhoPhi,U) Gauss linearUpwindV grad(U); • For the term div(phi,alpha) we are using interfaceCompression
vanLeer interpolation scheme.
33 div(phi,alpha) Gauss interfaceCompression vanLeer 1;
• This is an interface compression corrected scheme used to
39 div(phi,k) Gauss upwind; maintain sharp interfaces in VOF simulations.
40 div(phi,epsilon) Gauss upwind;
41 div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; • The coefficient defines the degree of compression, where 1 is
42 }
43
suitable for most VOF applications.
44 laplacianSchemes • For the terms div(phi,k) and div(phi,epsilon) we are using upwind
45 {
46 default Gauss linear corrected; (these terms are related to the turbulence modeling).
47 }
48
• For the term div(((rho*nuEff)*dev2(T(grad(U))))) we are using
49 interpolationSchemes linear interpolation (this term is related to the turbulence modeling).
50 {
51 default linear; • For the discretization of the Laplacian (laplacianSchemes and
52 } snGradSchemes) we are using the Gauss linear corrected method
53
54 snGradSchemes • In overall, this method is second order accurate but a little bit
55 { diffusive. Remember, at the end of the day we want a solution that is
56 default corrected;
57 } second order accurate.
168
3D Dam break – Free surface flow
The fvSolution dictionary
169
3D Dam break – Free surface flow
The fvSolution dictionary
170
3D Dam break – Free surface flow
The fvSolution dictionary
• Be careful not use too low values as you will loose time
accuracy.
• If you want to disable under-relaxation, comment out
these lines.
• The option momentumPredictor (line 85), is recommended for
highly convective flows.
171
3D Dam break – Free surface flow
The system directory
• In the system directory you will find the following optional dictionary files:
• decomposeParDict
• setFieldsDict
172
3D Dam break – Free surface flow
The setFieldsDict dictionary
• This dictionary file is located in the directory system.
• In lines 17-20 we set the default value to be 0 in the whole
17 defaultFieldValues domain (no water).
18 (
19
20 );
volScalarFieldValue alpha.water 0
• In lines 22-32, we initialize a rectangular region (box)
21 containing water (alpha.water 1).
22 regions
23
24
(
boxToCell
• In this case, setFields will look for the dictionary file
25 { alpha.water and it will overwrite the original values
26 box (1.992 -10 0) (5 10 0.55);
27 fieldValues according to the regions defined in setFieldsDict.
28 (
29 volScalarFieldValue alpha.water 1 • We initialize the water phase because is the primary phase in
30 );
31 } the dictionary transportProperties.
32 );
• If you are interested in initializing the vector field U, you can
proceed as follows volVectorFieldValue U (0 0 0)
Air
alpha.water = 0
Water
alpha.water = 1
boxToCell region
173
3D Dam break – Free surface flow
The decomposeParDict dictionary
• This dictionary file is located in the directory system.
• This dictionary is used to decompose the domain in order to run in parallel.
• The keyword numberOfSubdomains (line 17) is used to set the number of cores we want to use in the
parallel simulation.
• In this dictionary we also set the decomposition method (line 19).
• Most of the times the scotch method is fine.
• In this case we set the numberOfSubdomains to 4, therefore we will run in parallel using 4 cores.
17 numberOfSubdomains 4;
18
19 method scotch;
20
• When you run in parallel, the solution is saved in the directories processorN, where N stands for processor
number. In this case you will find the following directories with the decomposed mesh and solution:
processor0, processor1, processor2, and processor3.
174
3D Dam break – Free surface flow
1. $> foamCleanTutorials
2. $> rm –rf 0
3. $> blockMesh
4. $> surfaceFeatures
5. $> snappyHexMesh -overwrite
6. $> createPatch -dict system/createPatchDict.0 -overwrite
7. $> createPatch -dict system/createPatchDict.1 -overwrite
8. $> checkMesh
9. $> paraFoam
175
3D Dam break – Free surface flow
1. $> rm –rf 0
2. $> cp –r 0_org 0
3. $> setFields
4. $> paraFoam
5. $> decomposePar
6. $> mpirun –np 4 interFoam –parallel | tee log.interFoam
7. $> reconstructPar
8. $> paraFoam
176
3D Dam break – Free surface flow
177
3D Dam break – Free surface flow
• To plot the sampled data using gnuplot you can proceed as follows. To enter to the
gnuplot prompt type in the terminal:
1. $> gnuplot
179
3D Dam break – Free surface flow
2. Select alpha.water in
the Active Variable drop-
down menu
Air Water
alpha.water = 0 alpha.water = 1
Interface
alpha.water = 0.5
181
3D Dam break – Free surface flow
4. Press apply
182
3D Dam break – Free surface flow
4. Press apply
183
3D Dam break – Free surface flow
Exercises
• Instead of using the boundary condition totalPressure and pressureInletOutletVelocity for the patch top, try
to use zeroGradient. Do you get the same results? Any comments?
(Hint: this combination of boundary conditions might give you an error, if so, read carefully the screen
and try to find a fix, you can start by looking at the file fvSolution)
• Instead of using the boundary condition fixedFluxPressure for the walls, try to use zeroGradient. Do you get
the same results? Any comments?
• Run the simulation in a close domain. Does the volume integral of alpha.water remains the same? Why the
value is not constant when the domain is open?
• Use a functionObject to measure the average pressure on the obstacle.
• How many initialization methods are there available in the dictionary setFieldsDict?
(Hint: use the banana method)
• Run the simulation using Gauss upwind instead of Gauss vanLeer or Gauss interfaceCompression
vanLeer 1 for the term div(phi,alpha) (fvSchemes). Do you get the same quantitative results?
184
3D Dam break – Free surface flow
Exercises
• Run a numerical experiment for cAlpha equal to 0, 1, and 2. Do you see any difference in the solution? What
about computing time?
• Use the solver GAMG instead of using the solver PCG for the variable p_rgh. Do you see any difference on
the solution or computing time?
• Increase the number of nOuterCorrector to 2 and study the output screen. What difference do you see?
• Turn off the MULES corrector (MULESCorr). Do you see any difference on the solution or computing time?
• If you set the gravity vector to (0 0 0), what do you think will happen?
• Try to break the solver and identify the cause of the error. You are free to try any kind of setup.
185
Roadmap
186
Flow past a cylinder – From laminar to turbulent flow
187
Flow past a cylinder – From laminar to turbulent flow
Flow around a cylinder – 10 < Re < 2 000 000
Incompressible and compressible flow
188
Flow past a cylinder – From laminar to turbulent flow
Workflow of the case
blockMesh
Or
fluentMeshToFoam
icoFoam
NOTE: pisoFoam
One single mesh can be used with all
solvers and utilities pimpleFoam
pimpleDyMFoam
simpleFoam
functionObjects
rhoPimpleFoam
interFoam
sonicFoam
potentialFoam
mapFields
postProcessing
utilities
sampling paraview
189
Flow past a cylinder – From laminar to turbulent flow
Strouhal number
190
Flow past a cylinder – From laminar to turbulent flow
Some experimental (E) and numerical (N) results of the flow past a circular
cylinder at various Reynolds numbers
[1] D. Tritton. Experiments on the flow past a circular cylinder at low Reynolds numbers. Journal of Fluid Mechanics, 6:547-567, 1959.
[2] M. Cuntanceau and R. Bouard. Experimental determination of the main features of the viscous flow in the wake of a circular cylinder in uniform translation. Part 1. Steady flow. Journal of Fluid
Mechanics, 79:257-272, 1973.
[3] D. Rusell and Z. Wang. A cartesian grid method for modeling multiple moving objects in 2D incompressible viscous flow. Journal of Computational Physics, 191:177-205, 2003.
[4] D. Calhoun and Z. Wang. A cartesian grid method for solving the two-dimensional streamfunction-vorticity equations in irregular regions. Journal of Computational Physics. 176:231-275, 2002.
[5] T. Ye, R. Mittal, H. Udaykumar, and W. Shyy. An accurate cartesian grid method for viscous incompressible flows with complex immersed boundaries. Journal of Computational Physics,
156:209-240, 1999.
[6] B. Fornberg. A numerical study of steady viscous flow past a circular cylinder. Journal of Fluid Mechanics, 98:819-855, 1980.
[7] J. Guerrero. Numerical simulation of the unsteady aerodynamics of flapping flight. PhD Thesis, University of Genoa, 2009.
191
Flow past a cylinder – From laminar to turbulent flow
Some experimental (E) and numerical (N) results of the flow past a circular
cylinder at various Reynolds numbers
[1] Russel and Wang (N) 1.38 ± 0.007 ± 0.322 1.29 ± 0.022 ± 0.50
[2] Calhoun and Wang (N) 1.35 ± 0.014 ± 0.30 1.17 ± 0.058 ± 0.67
[3] Braza et al. (N) 1.386± 0.015 ± 0.25 1.40 ± 0.05 ± 0.75
[4] Choi et al. (N) 1.34 ± 0.011 ± 0.315 1.36 ± 0.048 ± 0.64
[5] Liu et al. (N) 1.35 ± 0.012 ± 0.339 1.31 ± 0.049 ± 0.69
[1] D. Rusell and Z. Wang. A cartesian grid method for modeling multiple moving objects in 2D incompressible viscous flow. Journal of Computational Physics, 191:177-205, 2003.
[2] D. Calhoun and Z. Wang. A cartesian grid method for solving the two-dimensional streamfunction-vorticity equations in irregular regions. Journal of Computational Physics. 176:231-275, 2002.
[3] M. Braza, P. Chassaing, and H. Hinh. Numerical study and physical analysis of the pressure and velocity fields in the near wake of a circular cylinder. Journal of Fluid Mechanics, 165:79-130,
1986.
[4] J. Choi, R. Oberoi, J. Edwards, an J. Rosati. An immersed boundary method for complex incompressible flows. Journal of Computational Physics, 224:757-784, 2007.
[5] C. Liu, X. Zheng, and C. Sung. Preconditioned multigrid methods for unsteady incompressible flows. Journal of Computational Physics, 139:33-57, 1998.
[6] J. Guerrero. Numerical Simulation of the unsteady aerodynamics of flapping flight. PhD Thesis, University of Genoa, 2009.
192
Flow past a cylinder – From laminar to turbulent flow
At the end of the day, you should get something like this
193
Flow past a cylinder – From laminar to turbulent flow
At the end of the day, you should get something like this
$PTOFC/101OF/vortex_shedding
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
195
Flow past a cylinder – From laminar to turbulent flow
What are we going to do?
• We will use this case to learn how to use different solvers and utilities.
• Remember, different solvers have different input dictionaries.
• We will learn how to convert the mesh from a third-party software.
• We will learn how to use setFields to initialize the flow field and accelerate the
convergence.
• We will learn how to map a solution from a coarse mesh to a fine mesh.
• We will learn how to setup a compressible solver.
• We will learn how to setup a turbulence case.
• We will use gnuplot to plot and compute the mean values of the lift and drag
coefficients.
• We will visualize unsteady data.
196
Flow past a cylinder – From laminar to turbulent flow
Running the case
• Let us first convert the mesh from a third-party format (Fluent format).
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c2
• In the terminal window type:
1. $> foamCleanTutorials
2. $> fluent3DMeshToFoam ../../../meshes_and_geometries/vortex_shedding/ascii.msh
3. $> checkMesh
4. $> paraFoam
• In step 2, we convert the mesh from Fluent format to OpenFOAM® format. Have in
mind that the Fluent mesh must be in ascii format.
• If we try to open the mesh using paraFoam (step 4), it will crash. Can you tell what is
the problem by just reading the screen?
197
Flow past a cylinder – From laminar to turbulent flow
Running the case
• To avoid this problem, type in the terminal,
• Basically, the problem is related to the names and type of the patches in the file
boundary and the boundary conditions (U, p). Notice that OpenFOAM® is telling you
what and where is the error.
FOAM exiting
198
Flow past a cylinder – From laminar to turbulent flow
• Remember, when converting meshes the name and type of the patches are not
always set as you would like, so it is always a good idea to take a look at the file
boundary and modify it according to your needs.
• Let us modify the boundary dictionary file.
• In this case, we would like to setup the following numerical type boundary
conditions.
199
Flow past a cylinder – From laminar to turbulent flow
The boundary dictionary file
200
Flow past a cylinder – From laminar to turbulent flow
The boundary dictionary file
201
Flow past a cylinder – From laminar to turbulent flow
• At this point, check that the name and type of the base type boundary conditions
and numerical type boundary conditions are consistent. If everything is ok, we are
ready to go.
• Do not forget to explore the rest of the dictionary files, namely:
• 0/p (p is defined as relative pressure)
• 0/U
• constant/transportProperties
• system/controlDict
• system/fvSchemes
• system/fvSolution
• Reminder:
• The diameter of the cylinder is 2.0 m.
• And we are targeting for a Re = 200.
202
Flow past a cylinder – From laminar to turbulent flow
Running the case
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c2
• In the folder c1 you will find the same setup, but to generate the mesh we use
blockMesh (the mesh is identical).
• To run this case, in the terminal window type:
5. $> paraFoam
203
Flow past a cylinder – From laminar to turbulent flow
Running the case
• In step 1 we use the utility renumberMesh to make the linear system more diagonal
dominant, this will speed-up the linear solvers. This is inexpensive (even for large
meshes), therefore is highly recommended to always do it.
• In step 2 we run the simulation and save the log file. Notice that we are sending the
job to background.
• In step 3 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
job is running in background, we can launch this utility in the same terminal tab.
• In step 4 we use the gnuplot script scripts0/plot_coeffs to plot the force
coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
• The force coefficients are computed using functionObjects.
• After the simulation is over, we use paraFoam to visualize the results. Remember to
use the VCR Controls to animate the solution.
• In the folder c1 you will find the same setup, but to generate the mesh we use
blockMesh (the mesh is identical).
204
Flow past a cylinder – From laminar to turbulent flow
• At this point try to use the following utilities. In the terminal type:
• $> postProcess –func vorticity –noZero
This utility will compute and write the vorticity field. The –noZero option means do not compute the vorticity field for the
solution in the directory 0. If you do not add the –noZero option, it will compute and write the vorticity field for all the
saved solutions, including 0
• $> postprocess –func 'grad(U)' –latestTime
This utility will compute and write the velocity gradient or grad(U) in the whole domain (including at the walls). The
–latestTime option means compute the velocity gradient only for the last saved solution.
• $> postprocess –func 'grad(p)'
This utility will compute and write the pressure gradient or grad(U) in the whole domain (including at the walls).
• $> foamToVTK –time 50:300
This utility will convert the saved solution from OpenFOAM® format to VTK format. The –time 50:300 option means
convert the solution to VTK format only for the time directories 50 to 300
This utility will compute and write the divergence of the velocity field or grad(U) in the whole domain (including at the
walls).
• $> pisoFoam -postProcess -func CourantNo
This utility will compute and write the Courant number. This utility needs to access the solver database for the physical
properties and additional quantities; therefore we need to tell what solver we are using. As the solver icoFoam does not
accept the option –postProcess, we can use the solver pisoFoam instead. Remember, icoFoam is a fully laminar
solver and pisoFoam is a laminar/turbulent solver.
• $> pisoFoam -postProcess -func wallShearStress
This utility will compute and write the wall shear stresses at the walls. As no arguments are given, it will save the wall
shear stresses for all time steps.
205
Flow past a cylinder – From laminar to turbulent flow
Non-uniform field initialization
• In the previous case, it took about 150 seconds of simulation time to onset the instability.
• If you are not interested in the initial transient or if you want to speed-up the computation, you
can add a perturbation in order to trigger the onset of the instability.
• Let us use the utility setFields to initialize a non-uniform flow.
• This case is already setup in the directory ,
$PTOFC/101OF/vortex_shedding/c3
• As you saw in the previous example, icoFoam is a very basic solver that does not have access
to all the advanced modeling or postprocessing capabilities that comes with OpenFOAM®.
• Therefore, instead of using icoFoam we will use pisoFoam (or pimpleFoam) from now on.
• To run the solver pisoFoam (or pimpleFoam) starting from the directory structure of an
icoFoam case, you will need to add the followings modifications:
• Add the file momentumTransport in the directory constant.
• Add the transportModel to be used in the file constant/transportProperties.
• Add the entry div((nuEff*dev2(T(grad(U))))) Gauss linear; to the dictionary
system/fvSchemes in the section divSchemes (this entry is related to the Reynodls
stresses).
206
Flow past a cylinder – From laminar to turbulent flow
• Let us run the same case but using a non-uniform field
The setFieldsDict dictionary
• This dictionary file is located in the directory system.
17 defaultFieldValues • In lines 17-20 we set the default value of the velocity vector
18 (
19 volVectorFieldValue U (1 0 0) to be (0 0 0) in the whole domain.
20 );
21 • In lines 24-31, we initialize a rectangular region (box) just
22 regions
23 ( behind the cylinder with a velocity vector equal to (0.98480
24 boxToCell 0.17364 0)
25 {
26 box (0 -100 -100) (100 100 100);
27 fieldValues • In this case, setFields will look for the dictionary file U
28
29
(
volVectorFieldValue U (0.98480 0.17364 0)
and it will overwrite the original values according to the
30 ); regions defined in setFieldsDict.
31 }
32 );
boxToCell region
U (0.98480 0.17364 0)
U (1 0 0)
207
Flow past a cylinder – From laminar to turbulent flow
• Let us run the same case but using a non-uniform field.
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c3
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. Hereafter, we will
use blockMesh.
• To run this case, in the terminal window type:
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0 > /dev/null 2>&1
4. $> cp –r 0_org/ 0
5. $> setFields
6. $> renumberMesh -overwrite
7. $> pisoFoam | tee log.solver
$> pyFoamPlotWatcher.py log.pisofoam
8.
You will need to launch this script in a different terminal
209
Flow past a cylinder – From laminar to turbulent flow
Does non-uniform field initialization make a difference?
• A picture is worth a thousand words. No need to tell you yes, even if the solutions are
slightly different.
• This bring us to the next subject, for how long should we run the simulation?
210
Flow past a cylinder – From laminar to turbulent flow
For how long should run the simulation?
211
Flow past a cylinder – From laminar to turbulent flow
What about the residuals?
212
Flow past a cylinder – From laminar to turbulent flow
How to compute force coefficients
213
Flow past a cylinder – From laminar to turbulent flow
Can we compute basic statistics of the force coefficients using gnuplot?
• Yes we can. Enter the gnuplot prompt and type:
4. gnuplot> exit
To exit gnuplot
214
Flow past a cylinder – From laminar to turbulent flow
On the solution accuracy
17 ddtSchemes
• At the end of the day we want a solution that is second order
18 { accurate.
20 default backward;
22
23
}
• We define the discretization schemes (and therefore the
24 gradSchemes accuracy) in the dictionary fvSchemes.
25 {
29
35 }
default cellLimited leastSquares 1;
• In this case, for time discretization (ddtSchemes) we are
36 using the backward method.
37 divSchemes
38
39
{
default none;
• For gradient discretization (gradSchemes) we are using the
43 div(phi,U) Gauss linearUpwindV default; leastSquares method with slope limiters (cellLimited) for all
48 div((nuEff*dev2(T(grad(U))))) Gauss linear;
49 } terms (default option).
50
51 laplacianSchemes • Sometimes adding a gradient limiter to the pressure gradient
52 {
53 default Gauss linear limited 1; or grad(p) can be too diffusive, so it is better not to use
54
55
}
gradient limiters for grad(p), e.g., grad(p) leastSquares.
56 interpolationSchemes
57 { • For the discretization of the convective terms (divSchemes)
58
59 }
default linear;
we are using linearUpwindV interpolation method for the
60 term div(rho,U).
61 snGradSchemes
62
63
{
default limited 1;
• For the discretization of the Laplacian (laplacianSchemes
64 } and snGradSchemes) we are using the Gauss linear
limited 1 method
• In overall, this method is second order accurate (this is what
we want).
215
Flow past a cylinder – From laminar to turbulent flow
On the solution tolerance and linear solvers
17 solvers
• We define the solution tolerance and linear solvers in the
18 { dictionary fvSolution.
31 p
32
33
{
solver GAMG;
• To solve the pressure (p) we are using the GAMG method
34 tolerance 1e-6; with an absolute tolerance of 1e-6 and a relative tolerance
35 relTol 0;
36 smoother GaussSeidel; relTol of 0.01.
37 nPreSweeps 0;
38 nPostSweeps 2; • The entry pFinal refers to the final correction of the PISO
39 cacheAgglomeration on;
40 agglomerator faceAreaPair; loop. It is possible to use a tighter convergence criteria only
41
42
nCellsInCoarsestLevel 100;
mergeLevels 1;
in the last iteration.
43 }
44 • To solve U we are using the solver PBiCGStab and the DILU
45
46
pFinal
{
preconditioner, with an absolute tolerance of 1e-8 and a
47 $p; relative tolerance relTol of 0 (the solver will stop iterating
48 relTol 0;
49 } when it meets any of the conditions).
50
51 U • Solving for the velocity is relative inexpensive, whereas
52 {
53 solver PBiCGStab; solving for the pressure is expensive.
54 preconditioner DILU;
55 tolerance 1e-08; • The PISO sub-dictionary contains entries related to the
56 relTol 0;
57 } pressure-velocity coupling (in this case the PISO method).
69
70
}
Hereafter we are doing two PISO correctors (nCorrectors)
71 PISO and two non-orthogonal corrections
72 {
73 nCorrectors 2; (nNonOrthogonalCorrectors).
74 nNonOrthogonalCorrectors 2;
77 }
216
Flow past a cylinder – From laminar to turbulent flow
On the runtime parameters
17 application pisoFoam;
• This case starts from the latest saved solution (startFrom).
18
20 startFrom latestTime; • In this case as there are no saved solutions, it will start from
21
22 startTime 0;
0 (startTime).
23
24 stopAt endTime; • It will run up to 350 seconds (endTime).
26
27 endTime 350; • The time step of the simulation is 0.05 seconds (deltaT). The
28
29 deltaT 0.05; time step has been chosen in such a way that the Courant
30
31 writeControl runTime;
number is less than 1
32
33 writeInterval 1; • It will write the solution every 1 second (writeInterval) of
34
35 purgeWrite 0;
simulation time (runTime).
36
37 writeFormat ascii; • It will keep all the solution directories (purgeWrite).
38
39
40
writePrecision 8; • It will save the solution in ascii format (writeFormat).
41 writeCompression off;
42 • The write precision is 8 digits (writePrecision).
43 timeFormat general;
44 • And as the option runTimeModifiable is on, we can modify
45 timePrecision 6;
46 all these entries while we are running the simulation.
47 runTimeModifiable true;
217
Flow past a cylinder – From laminar to turbulent flow
The output screen
• This is the output screen of the pisoFoam solver.
nCorrector 1
Time = 350
Courant number
Courant Number mean: 0.11299953 max: 0.87674198
DILUPBiCG: Solving for Ux, Initial residual = 0.0037946307, Final residual = 4.8324843e-09, No Iterations 3
DILUPBiCG: Solving for Uy, Initial residual = 0.011990022, Final residual = 5.8815028e-09, No Iterations 3
GAMG: Solving for p, Initial residual = 0.022175872, Final residual = 6.2680545e-07, No Iterations 14
GAMG: Solving for p, Initial residual = 0.0033723932, Final residual = 5.8494331e-07, No Iterations 8
nNonOrthogonalCorrectors 2
GAMG: Solving for p, Initial residual = 0.0010074964, Final residual = 4.4726195e-07, No Iterations 7
time step continuity errors : sum local = 1.9569266e-11, global = -3.471923e-14, cumulative = -2.8708402e-10
GAMG: Solving for p, Initial residual = 0.0023505548, Final residual = 9.9222424e-07, No Iterations 8
GAMG: Solving for p, Initial residual = 0.00045248026, Final residual = 7.7250386e-07, No Iterations 6
GAMG: Solving for p, Initial residual = 0.00014664077, Final residual = 4.5825218e-07, No Iterations 5 pFinal
time step continuity errors : sum local = 2.0062733e-11, global = 1.2592813e-13, cumulative = -2.8695809e-10
ExecutionTime = 746.46 s ClockTime = 807 s
218
Flow past a cylinder – From laminar to turbulent flow
Let us use a potential solver to find a quick solution
• In this case we are going to use the potential solver potentialFoam (remember potential
solvers are inviscid, irrotational and incompressible)
• This solver is super fast, and it can be used to find a solution to be used as initial conditions
(non-uniform field) for an incompressible solver.
• A good initial condition will accelerate and improve the convergence rate.
• This case is already setup in the directory
$PTOFC/101OF/vortex_shedding/c4
219
Flow past a cylinder – From laminar to turbulent flow
Running the case – Let us use a potential solver to find a quick solution
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0
4. $> cp –r 0_org 0
5. $> potentialFoam –noFunctionObjects –initialiseUBCs –writep -writePhi
6. $> paraFoam
220
Flow past a cylinder – From laminar to turbulent flow
Running the case – Let us use a potential solver to find a quick solution
• In step 2 we generate the mesh using blockMesh. The name and type of the
patches are already set in the dictionary blockMeshDict so there is no need to
modify the boundary file.
• In step 4 we copy the original files to the directory 0. We do this to keep a backup of
the original files as they will be overwritten by the solver potentialFoam.
• In step 5 we run the solver. We use the option –noFunctionObjects to avoid
conflicts with the functionobjects. The options –writep and –writePhi will write
the pressure field and fluxes respectively.
• At this point, if you want to use this solution as initial conditions for an incompressible
solver, just copy the files U and p into the start directory of the incompressible case
you are looking to run. Have in mind that the meshes need to be the same.
• Be careful with the name and type of the boundary conditions, they should be same
between the potential case and incompressible case.
221
Flow past a cylinder – From laminar to turbulent flow
Potential solution
• Using a potential solution as initial conditions is much better than using a uniform
flow. It will speed up the solution and it will give you more stability.
• Finding a solution using the potential solver is inexpensive.
222
Flow past a cylinder – From laminar to turbulent flow
The output screen
• This is the output screen of the potentialFoam solver.
• The output of this solver is also a good indication of the sensitivity of the mesh quality
to gradients computation. If you see that the number of iterations are dropping
iteration after iteration, it means that the mesh is fine.
• If the number of iterations remain stalled, it means that the mesh is sensitive to
gradients, so you should use non-orthogonal correction.
• In this case we have a good mesh.
End
223
Flow past a cylinder – From laminar to turbulent flow
Let us map a solution from a coarse mesh to a finer mesh
• It is also possible to map the solution from a coarse mesh to a finer mesh (and all the
way around).
• For instance, you can compute a full Navier-Stokes solution in a coarse mesh (fast
solution), and then map it to a finer mesh.
• Let us map the solution from the potential solver to a finer mesh (if you want you can
map the solution obtained using pisoFoam or icoFoam). To do this we will use the
utility mapFields.
• This case is already setup in the directory
$PTOFC/101OF/vortex_shedding/c6
224
Flow past a cylinder – From laminar to turbulent flow
Running the case – Let us map a solution from a coarse mesh to a finer mesh
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0
4. $> cp –r 0_org 0
5. $> mapfields ../c4 –consistent –noFunctionObjects –mapMethod cellPointInterpolate -sourceTime 0
6. $> paraFoam
225
Flow past a cylinder – From laminar to turbulent flow
Running the case – Let us map a solution from a coarse mesh to a finer mesh
• In step 2 we generate a finer mesh using blockMesh. The name and type of the
patches are already set in the dictionary blockMeshDict so there is no need to
modify the boundary file.
• In step 4 we copy the original files to the directory 0. We do this to keep a backup of
the original files as they will be overwritten by the utility mapFields.
• In step 5 we use the utility mapFields with the following options:
• We copy the solution from the directory ../c4
• The options –consistent is used when the domains and BCs are the same.
• The option –noFunctionObjects is used to avoid conflicts with the
functionObjects.
• The option –mapMethod cellPointInterpolate defines the interpolation
method.
• The option -sourceTime 0 defines the time from which we want to interpolate
the solution.
226
Flow past a cylinder – From laminar to turbulent flow
The meshes and the mapped fields
mapFields
227
Flow past a cylinder – From laminar to turbulent flow
The output screen
• This is the output screen of the mapFields utility.
• The utility mapFields, will try to interpolate all fields in the source directory.
• You can control the target time via the startFrom and startTime keywords in the
controlDict dictionary file.
Source: "/home/joegi/my_cases_course/OF8/101OF/vortex_shedding" "c5" Source case
Target: "/home/joegi/my_cases_course/OF8/101OF/vortex_shedding" "c6" Target case
Mapping method: cellPointInterpolate Interpolation method
Source mesh size: 9200 Target mesh size: 36800 Source and target mesh cell count
interpolating Phi
interpolating p Interpolated fields
interpolating U
End
• Finally, after mapping the solution, you can run the solver in the usual way. The solver
will use the mapped solution as initial conditions. 228
Flow past a cylinder – From laminar to turbulent flow
Setting a turbulent case
• So far we have used laminar incompressible solvers.
• Let us do a turbulent simulation.
• When doing turbulent simulations, we need to choose the turbulence model, define
the boundary and initial conditions for the turbulent quantities, and modify the
fvSchemes and fvSolution dictionaries to take account for the new variables we
are solving (the transported turbulent quantities).
• This case is already setup in the directory
$PTOFC/101OF/vortex_shedding/c14
229
Flow past a cylinder – From laminar to turbulent flow
• The following dictionaries remain unchanged
• system/blockMeshDict
• constant/polyMesh/boundary
• 0/p
• 0/U
16 transportModel Newtonian;
17
19 nu nu [ 0 2 -1 0 0 0 0 ] 0.0002;
• Reminder:
• The diameter of the cylinder is 2.0 m.
• And we are targeting for a Re = 10000.
231
Flow past a cylinder – From laminar to turbulent flow
The momentumTransport dictionary file
• This dictionary file is located in the directory constant.
• In this dictionary file we select what model we would like to use (laminar or turbulent).
• In this case we are interested in modeling turbulence, therefore the dictionary is as follows
• If you want to know the models available use the banana method.
232
Flow past a cylinder – From laminar to turbulent flow
The controlDict dictionary
17 application pimpleFoam;
• This case will start from the last saved solution (startFrom). If there is
18 no solution, the case will start from time 0 (startTime).
20 startFrom latestTime;
21 • It will run up to 500 seconds (endTime).
22 startTime 0;
23 • The initial time step of the simulation is 0.001 seconds (deltaT).
24 stopAt endTime;
25
26 endTime 500;
• It will write the solution every 1 second (writeInterval) of simulation time
27 (runTime).
28 deltaT 0.001;
29 • It will keep all the solution directories (purgeWrite).
30 writeControl runTime;
31 • It will save the solution in ascii format (writeFormat).
32 writeInterval 1;
33
34 purgeWrite 0;
• The write precision is 8 digits (writePrecision).
35
36 writeFormat ascii; • And as the option runTimeModifiable is on, we can modify all these
37 entries while we are running the simulation.
38 writePrecision 8;
39 • In line 48 we turn on the option adjustTimeStep. This option will
40 writeCompression off;
41 automatically adjust the time step to achieve the maximum desired
42 timeFormat general; courant number maxCo (line 50).
43
44 timePrecision 6; • We also set a maximum time step maxDeltaT in line 51.
45
46 runTimeModifiable yes; • Remember, the first time-step of the simulation is done using the value
47
48 adjustTimeStep yes; set in line 28 and then it is automatically scaled to achieve the desired
49 maximum values (lines 50-51).
50 maxCo 0.9;
51 maxDeltaT 0.1; • The feature adjustTimeStep is only present in the PIMPLE family
solvers, but it can be added to any solver by modifying the source code.
233
Flow past a cylinder – From laminar to turbulent flow
The fvSchemes dictionary
234
Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary
17 solvers
• To solve the pressure (p) we are using the GAMG method, with an
18 { absolute tolerance of 1e-6 and a relative tolerance relTol of 0.001.
31 p Notice that we are fixing the number of minimum iterations (minIter).
32 {
33 solver GAMG;
34 tolerance 1e-6;
• To solve the final pressure correction (pFinal) we are using the PCG
35 relTol 0.001; method with the DIC preconditioner, with an absolute tolerance of 1e-6
36 smoother GaussSeidel; and a relative tolerance relTol of 0.
37 nPreSweeps 0;
38 nPostSweeps 2;
39 cacheAgglomeration on;
• Notice that we can use different methods between p and pFinal. In this
40 agglomerator faceAreaPair; case we are using a tighter tolerance for the last iteration.
41 nCellsInCoarsestLevel 100;
42 mergeLevels 1; • We are also fixing the number of minimum iterations (minIter). This
44 minIter 2;
45 }
entry is optional.
46
47 pFinal • To solve U we are using the solver PBiCGStab with the DILU
48 { preconditioner, an absolute tolerance of 1e-8 and a relative tolerance
49 solver PCG;
50 preconditioner DIC;
relTol of 0. Notice that we are fixing the number of minimum iterations
51 tolerance 1e-06; (minIter).
52 relTol 0;
53 minIter 3;
54 }
55
56 U
57 {
58 solver PBiCGStab;
59 preconditioner DILU;
60 tolerance 1e-08;
61 relTol 0;
62 minIter 3;
63 }
235
Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary
17 solvers
• To solve UFinal we are using the solver PBiCGStab with an absolute
18 { tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
fixing the number of minimum iterations (minIter).
77 UFinal
78 {
79 solver PBiCGStab;
• To solve omega and omegaFinal we are using the solver PBiCGStab
80 preconditioner DILU; with an absolute tolerance of 1e-8 and a relative tolerance relTol of 0.
81 tolerance 1e-08; Notice that we are fixing the number of minimum iterations (minIter).
82 relTol 0;
83 minIter 3;
84 }
• To solve k we are using the solver PBiCGStab with an absolute
85 tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
86 omega fixing the number of minimum iterations (minIter).
87 {
88 solver PBiCGStab;
89 preconditioner DILU;
90 tolerance 1e-08;
91 relTol 0;
92 minIter 3;
93 }
94
95 omegaFinal
96 {
97 solver PBiCGStab;
98 preconditioner DILU;
99 tolerance 1e-08;
100 relTol 0;
101 minIter 3;
102 }
103
104 k
105 {
106 solver PBiCGStab;
107 preconditioner DILU;
108 tolerance 1e-08;
109 relTol 0;
110 minIter 3;
111 }
236
Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary
113 kFinal
• To solve kFinal we are using the solver PBiCGStab with an absolute
114 { tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
115 solver PBiCGStab; fixing the number of minimum iterations (minIter).
116 preconditioner DILU;
117 tolerance 1e-08;
118 relTol 0;
• In lines 123-133 we setup the entries related to the pressure-velocity
119 minIter 3; coupling method used (PIMPLE in this case). Setting the keyword
120 } nOuterCorrectors to 1 is equivalent to running using the PISO method.
121 }
122
123 PIMPLE
• To gain more stability we are using 1 outer correctors
124 { (nOuterCorrectors), 3 inner correctors or PISO correctors
126 nOuterCorrectors 1; (nCorrectors), and 1 correction due to non-orthogonality
127 //nOuterCorrectors 2;
128 (nNonOrthogonalCorrectors).
129 nCorrectors 3;
130 nNonOrthogonalCorrectors 1; • Remember, adding corrections increase the computational cost.
133 }
134 • In lines 135-147 we setup the under-relaxation factors used during the
135 relaxationFactors
136 {
outer corrections of the PIMPLE method.
137 fields
138 { • The values defined correspond to the industry standard of the
139 p 0.3; SIMPLE method.
140 }
141 equations • By using under-relaxation we ensure diagonal equality.
142 {
143 U 0.7;
144 k 0.7;
• Be careful not use too low values as you will loose time accuracy.
145 omega 0.7;
146 } • If you want to disable under-relaxation, comment out these lines.
147 }
237
Flow past a cylinder – From laminar to turbulent flow
• The following dictionaries are new
• 0/k
• 0/omega
• 0/nut
These are the field variables related to the closure equations of the turbulent
model.
238
Flow past a cylinder – From laminar to turbulent flow
Turbulence model free-stream boundary conditions
• The initial value for the turbulent kinetic energy can be found as follows
• The initial value for the specific kinetic energy can be found as follows
• If you are working with external aerodynamics or virtual wind tunnels, you can use the following
reference values for the turbulence intensity and the viscosity ratio. They work most of the
times, but it is a good idea to have some experimental data or a better initial estimate.
1 10 100
239
Flow past a cylinder – From laminar to turbulent flow
The file 0/k
19 internalField uniform 0.00015;
20 • We are using uniform initial conditions (line 19).
21 boundaryField
22 { • For the in patch we are using a fixedValue boundary
23 out
24 { condition.
25 type inletOutlet;
26 inletValue uniform 0.00015; • For the out patch we are using an inletOutlet boundary
27 value uniform 0.00015;
28 } condition (this boundary condition avoids backflow).
29 sym1
30
31
{
type symmetryPlane;
• For the cylinder patch (which is base type wall), we
32 } are using the kqRWallFunction boundary condition.
33 sym2
34 {
This is a wall function, we are going to talk about this
35 type symmetryPlane; when we deal with turbulence modeling. Remember,
36 }
37 in we can use wall functions only if the patch is of base
38
39
{
type fixedValue;
type wall.
40 value uniform 0.00015;
41 } • The rest of the patches are constrained.
42 cylinder
43
44
{
type kqRWallFunction;
• FYI, the inlet velocity is 1 and the turbulence intensity is
45 value uniform 0.00015; equal to 1%.
46 }
47
48
back
{
• We will study with more details how to setup the
49 type empty; boundary conditions when we deal with turbulence
50 }
51 front modeling in the advanced modules.
52 {
53 type empty;
54 }
55 }
240
Flow past a cylinder – From laminar to turbulent flow
The file 0/omega
19 internalField uniform 0.075;
20
21 boundaryField • We are using uniform initial conditions (line 19).
22 {
23 out • For the in patch we are using a fixedValue boundary
24 {
25 type inletOutlet; condition.
26 inletValue uniform 0.075;
27
28 }
value uniform 0.075; • For the out patch we are using an inletOutlet boundary
29 sym1 condition (this boundary condition avoids backflow).
30 {
31
32 }
type symmetryPlane;
• For the cylinder patch (which is base type wall), we
33 sym2 are using the omegaWallFunction boundary condition.
34 {
35 type symmetryPlane; This is a wall function; we are going to talk about this
36
37
}
in
when we deal with turbulence modeling. Remember, we
38 { can use wall functions only if the patch is of base type
39
40
type
value
fixedValue;
uniform 0.075;
wall.
41 }
42 cylinder • The rest of the patches are constrained.
43 {
44
45
type
Cmu
omegaWallFunction;
0.09;
• FYI, the inlet velocity is 1 and the eddy viscosity ratio is
46 kappa 0.41; equal to 10.
47 E 9.8;
48
49
beta1
value
0.075;
uniform 0.075;
• We will study with more details how to setup the
50 } boundary conditions when we deal with turbulence
51 back
52 { modeling in the advanced modules.
53 type empty;
54 }
55 front
56 {
57 type empty;
58 }
59 }
241
Flow past a cylinder – From laminar to turbulent flow
The file 0/nut
19 internalField uniform 0;
20 • We are using uniform initial conditions (line 19).
21 boundaryField
22
23
{
out
• For the in patch we are using the calculated boundary
24 { condition (nut is computed from kappa and omega)
25 type calculated;
26
27 }
value uniform 0; • For the out patch we are using the calculated
28 sym1 boundary condition (nut is computed from kappa and
29 {
30 type symmetryPlane; omega)
31 }
32 sym2 • For the cylinder patch (which is base type wall), we
33 {
34 type symmetryPlane; are using the nutkWallFunction boundary condition.
35
36
}
in
This is a wall function, we are going to talk about this
37 { when we deal with turbulence modeling. Remember, we
38 type calculated;
39 value uniform 0;
can use wall functions only if the patch is of base type
40 } wall.
41 cylinder
42 {
43 type nutkWallFunction; • The rest of the patches are constrained.
44 Cmu 0.09;
45 kappa 0.41; • Remember, the turbulent viscosity (nut) is equal to
46 E 9.8;
47 value uniform 0;
48 }
49 back
50 {
51 type empty;
52 } • We will study with more details how to setup the
53 front
54 { boundary conditions when we deal with turbulence
55
56 }
type empty;
modeling in the advanced modules.
57 }
242
Flow past a cylinder – From laminar to turbulent flow
Running the case – Setting a turbulent case
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c14
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this case we will use
blockMesh.
• To run this case, in the terminal window type:
1. $> foamCleanTutorials
2. $> blockMesh
3. $> renumberMesh -overwrite
$> pimpleFoam | tee log.solver
4.
You will need to launch this script in a different terminal
8. $> paraFoam
243
Flow past a cylinder – From laminar to turbulent flow
Running the case – Setting a turbulent case
• In step 3 we use the utility renumberMesh to make the linear system more diagonal
dominant, this will speed-up the linear solvers.
• In step 4 we run the simulation and save the log file. Notice that we are sending the
job to background.
• In step 5 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
job is running in background, we can launch this utility in the same terminal tab.
• In step 6 we use the gnuplot script scripts0/plot_coeffs to plot the force
coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
• In step 7 we use the utility postProcess to compute the value of each saved
solution (we are going to talk about when we deal with turbulence modeling).
244
Flow past a cylinder – From laminar to turbulent flow
pimpleFoam output screen
Courant Number mean: 0.088931706 max: 0.90251464 Courant number
deltaT = 0.040145538 Time step
Time = 499.97 Simulation time
PIMPLE: iteration 1 Outer iteration 1 (nOuterCorrectors)
DILUPBiCG: Solving for Ux, Initial residual = 0.0028528538, Final residual = 9.5497298e-11, No Iterations 3
DILUPBiCG: Solving for Uy, Initial residual = 0.0068876991, Final residual = 7.000938e-10, No Iterations 3
GAMG: Solving for p, Initial residual = 0.25644342, Final residual = 0.00022585963, No Iterations 7
GAMG: Solving for p, Initial residual = 0.0073871161, Final residual = 5.2798526e-06, No Iterations 8
time step continuity errors : sum local = 3.2664019e-10, global = -1.3568363e-12, cumulative = -9.8446438e-08
GAMG: Solving for p, Initial residual = 0.16889316, Final residual = 0.00014947209, No Iterations 7
GAMG: Solving for p, Initial residual = 0.0051876466, Final residual = 3.7123156e-06, No Iterations 8
time step continuity errors : sum local = 2.2950163e-10, global = -8.0710768e-13, cumulative = -9.8447245e-08
PIMPLE: iteration 2 Outer iteration 2 (nOuterCorrectors)
DILUPBiCG: Solving for Ux, Initial residual = 0.0013482181, Final residual = 4.1395468e-10, No Iterations 3
DILUPBiCG: Solving for Uy, Initial residual = 0.0032433196, Final residual = 3.3969121e-09, No Iterations 3
GAMG: Solving for p, Initial residual = 0.10067317, Final residual = 8.9325549e-05, No Iterations 7
GAMG: Solving for p, Initial residual = 0.0042844521, Final residual = 3.0190597e-06, No Iterations 8
time step continuity errors : sum local = 1.735023e-10, global = -2.0653335e-13, cumulative = -9.8447452e-08
GAMG: Solving for p, Initial residual = 0.0050231165, Final residual = 3.2656397e-06, No Iterations 8
DICPCG: Solving for p, Initial residual = 0.00031459519, Final residual = 9.4260163e-07, No Iterations 36 pFinal
time step continuity errors : sum local = 5.4344408e-11, global = 4.0060595e-12, cumulative = -9.8443445e-08
DILUPBiCG: Solving for omega, Initial residual = 0.00060510266, Final residual = 1.5946601e-10, No Iterations 3
DILUPBiCG: Solving for k, Initial residual = 0.0032163247, Final residual = 6.9350899e-10, No Iterations 3
bounding k, min: -3.6865398e-05 max: 0.055400108 average: 0.0015914926
ExecutionTime = 1689.51 s ClockTime = 1704 s
Time = 500.01
Reading field U
Writing yPlus to field yPlus Writing the field to the solution directory
246
Flow past a cylinder – From laminar to turbulent flow
Using a compressible solver
• So far, we have only used incompressible solvers.
• Let us use the compressible solver rhoPimpleFoam, which is a,
Transient solver for laminar or turbulent flow of compressible fluids for HVAC and
similar applications. Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-
resolved and pseudo-transient simulations.
$PTOFC/101OF/vortex_shedding/c24
247
Flow past a cylinder – From laminar to turbulent flow
• The following dictionaries remain unchanged
• system/blockMeshDict
• constant/polyMesh/boundary
• Reminder:
• The diameter of the cylinder is 0.002 m.
• The working fluid is air at 20° Celsius and at a sea level.
• Isothermal flow.
• And we are targeting for a Re = 200.
248
Flow past a cylinder – From laminar to turbulent flow
The constant directory
• thermophysicalProperties
• momentumTransport
249
Flow past a cylinder – From laminar to turbulent flow
The thermophysicalProperties dictionary file
250
Flow past a cylinder – From laminar to turbulent flow
The thermophysicalProperties dictionary file
251
Flow past a cylinder – From laminar to turbulent flow
The turbulenceProperties dictionary file
• In this dictionary file we select what model we would like to use (laminar or
turbulent).
• This dictionary is compulsory.
• As we do not want to model turbulence, the dictionary is defined as follows,
17 simulationType laminar;
252
Flow past a cylinder – From laminar to turbulent flow
The 0 directory
• In this directory, we will find the dictionary files that contain the boundary and
initial conditions for all the primitive variables.
• As we are solving the compressible laminar Navier-Stokes equations, we will
find the following field files:
• p (pressure)
• T (temperature)
• U (velocity field)
253
Flow past a cylinder – From laminar to turbulent flow
The file 0/p
• This file contains the boundary and initial conditions
17
18
dimensions [1 -1 -2 0 0 0 0];
for the scalar field pressure (p). We are working
19 internalField uniform 101325; with absolute pressure.
20
21
22
boundaryField
{
• Contrary to incompressible flows where we defined
23 in relative pressure, this is the absolute pressure.
24 {
25
26 }
type zeroGradient;
• Also, pay attention to the units (line 17). The
28 out pressure is defined in Pascal.
29 {
30
31
type
value
fixedValue;
uniform 101325;
• We are using uniform initial conditions (line 19).
32 }
34 cylinder • For the in patch we are using a zeroGradient
35 {
36 type zeroGradient; boundary condition.
37 }
39 sym1 • For the outlet patch we are using a fixedValue
40 {
41 type symmetryPlane; boundary condition.
42 }
44 sym2 • For the cylinder patch we are using a zeroGradient
45 {
46 type symmetryPlane; boundary condition.
47 }
49 back • The rest of the patches are constrained.
50 {
51 type empty;
52 }
54 front
55 {
56 type empty;
57 }
58 }
254
Flow past a cylinder – From laminar to turbulent flow
The file 0/T
17 dimensions [0 0 0 -1 0 0 0];
• This file contains the boundary and initial conditions
18 for the scalar field temperature (T).
19 internalField uniform 293.15;
20
21 boundaryField • Also, pay attention to the units (line 17). The
22 { temperature is defined in Kelvin.
23 in
24 {
25 type fixedValue; • We are using uniform initial conditions (line 19).
26 value $internalField;
27 } • For the in patch we are using a fixedValue boundary
29 out
30 { condition.
31 type inletOutlet;
32 value $internalField; • For the out patch we are using a inletOutlet
33 inletValue $internalField;
34 } boundary condition (in case of backflow).
36 cylinder
37 { • For the cylinder patch we are using a zeroGradient
38 type zeroGradient;
39 } boundary condition.
41 sym1
42 { • The rest of the patches are constrained.
43 type symmetryPlane;
44 }
46 sym2
47 {
48 type symmetryPlane;
49 }
51 back
52 {
53 type empty;
54 }
56 front
57 {
58 type empty;
59 }
60 }
255
Flow past a cylinder – From laminar to turbulent flow
The file 0/U
17 dimensions [0 1 -1 0 0 0 0];
18 • This file contains the boundary and initial conditions
19
20
internalField uniform (1.5 0 0); for the dimensional vector field U.
21 boundaryField
22 { • We are using uniform initial conditions and the
23
24
in
{
numerical value is (1.5 0 0) (keyword internalField in
25 type fixedValue; line 19).
26 value uniform (1.5 0 0);
27
29
}
out
• For the in patch we are using a fixedValue boundary
30 { condition.
31 type inletOutlet;
32
33
phi
inletValue
phi;
uniform (0 0 0);
• For the out patch we are using a inletOutlet
34 value uniform (0 0 0); boundary condition (in case of backflow).
35 }
37 cylinder
38 {
• For the cylinder patch we are using a zeroGradient
39 type fixedValue; boundary condition.
40 value uniform (0 0 0);
41 }
43 sym1 • The rest of the patches are constrained.
44 {
45 type symmetryPlane;
46 }
48 sym2
49 {
50 type symmetryPlane;
51 }
53 back
54 {
55 type empty;
56 }
58 front
59 {
60 type empty;
61 }
62 }
256
Flow past a cylinder – From laminar to turbulent flow
The system directory
257
Flow past a cylinder – From laminar to turbulent flow
The controlDict dictionary
17 application rhoPimpleFoam;
• This case will start from the last saved solution (startFrom). If there is
18 no solution, the case will start from time 0 (startTime).
19 startFrom startTime;
20 //startFrom latestTime; • It will run up to 0.3 seconds (endTime).
21
22 startTime 0; • The initial time step of the simulation is 0.00001 seconds (deltaT).
23
24 stopAt endTime;
25 //stopAt writeNow;
• It will write the solution every 0.0025 seconds (writeInterval) of
26 simulation time (adjustableRunTime). The option adjustableRunTime
27 endTime 0.3; will adjust the time-step to save the solution at the precise intervals. This
28
29 deltaT 0.00001; may add some oscillations in the solution as the CFL is changing.
30
31 writeControl adjustableRunTime; • It will keep all the solution directories (purgeWrite).
32
33 writeInterval 0.0025; • It will save the solution in ascii format (writeFormat).
34
35 purgeWrite 0; • And as the option runTimeModifiable is on, we can modify all these
36
37 writeFormat ascii; entries while we are running the simulation.
38
39 writePrecision 10; • In line 49 we turn on the option adjustTimeStep. This option will
40 automatically adjust the time step to achieve the maximum desired
41 writeCompression off;
42 courant number (line 50).
43 timeFormat general;
44 • We also set a maximum time step in line 51.
45 timePrecision 6;
46 • Remember, the first time step of the simulation is done using the value
47 runTimeModifiable true;
set in line 28 and then it is automatically scaled to achieve the desired
48
49 adjustTimeStep yes; maximum values (lines 66-67).
50 maxCo 1;
51 maxDeltaT 1; • The feature adjustTimeStep is only present in the PIMPLE family
solvers, but it can be added to any solver by modifying the source code.
258
Flow past a cylinder – From laminar to turbulent flow
The controlDict dictionary
235
236 };
259
Flow past a cylinder – From laminar to turbulent flow
The fvSchemes dictionary
260
Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary
17 solvers • To solve the pressure (p) we are using the PCG method with
18
20
{
p
an absolute tolerance of 1e-6 and a relative tolerance relTol
21 { of 0.01.
22 solver PCG;
23
24
preconditioner
tolerance
DIC;
1e-06;
• The entry pFinal refers to the final correction of the PISO
25 relTol 0.01; loop. Notice that we are using macro expansion ($p) to copy
26 minIter 2;
27 } the entries from the sub-dictionary p.
46 pFinal
47 { • To solve U and UFinal (U.*) we are using the solver
48 $p;
49 relTol 0; PBiCGStab with an absolute tolerance of 1e-8 and a relative
50
51 }
minIter 2;
tolerance relTol of 0.
53 "U.*"
54 { • To solve hFinal (enthalpy) we are using the solver
55
56
solver PBiCGStab;
preconditioner DILU;
PBiCGStab with an absolute tolerance of 1e-8 and a relative
57 tolerance 1e-08; tolerance relTol of 0.
58 relTol 0;
59
60 }
minIter 2;
• To solve rho and rhoFinal (rho.*) we are using the diagonal
74 hFinal solver (remember rho is found from the equation of state, so
75 {
76 solver PBiCGStab; this is a back-substitution).
77 preconditioner DILU;
78 tolerance 1e-08; • FYI, solving for the velocity is relative inexpensive, whereas
79 relTol 0;
80 minIter 2; solving for the pressure is expensive.
81 }
83 "rho.*" • Be careful with the enthalpy, it might cause oscillations.
84 {
85 solver diagonal;
86 }
87 }
261
Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary
262
Flow past a cylinder – From laminar to turbulent flow
Running the case – Using a compressible solver
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c24
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this case we will use
blockMesh.
• To run this case, in the terminal window type:
1. $> foamCleanTutorials
2. $> blockMesh
3. $> transformPoints –scale ‘(0.001 0.001 0.001)’
4. $> renumberMesh -overwrite
5. $> rhoPimpleFoam | tee log
$> pyFoamPlotWatcher.py log
6.
You will need to launch this script in a different terminal
264
Flow past a cylinder – From laminar to turbulent flow
rhoPimpleFoam output screen
Courant Number mean: 0.1280224248 max: 0.9885863338 Courant number
deltaT = 3.816512052e-05 Time step
Time = 0.3
diagonal: Solving for rho, Initial residual = 0, Final residual = 0, No Iterations 0 Solving for density (rho)
PIMPLE: iteration 1
DILUPBiCG: Solving for Ux, Initial residual = 0.003594731129, Final residual = 3.026673755e-11, No Iterations 5
DILUPBiCG: Solving for Uy, Initial residual = 0.01296036298, Final residual = 1.223236662e-10, No Iterations 5
DILUPBiCG: Solving for h, Initial residual = 0.01228951539, Final residual = 2.583236461e-09, No Iterations 4 h residuals
DICPCG: Solving for p, Initial residual = 0.01967621449, Final residual = 8.797612158e-07, No Iterations 77
DICPCG: Solving for p, Initial residual = 0.003109422612, Final residual = 9.943030465e-07, No Iterations 69
diagonal: Solving for rho, Initial residual = 0, Final residual = 0, No Iterations 0
time step continuity errors : sum local = 6.835363016e-11, global = 4.328592697e-12, cumulative = 2.366774797e-09
rho max/min : 1.201420286 1.201382023 pFinal
DICPCG: Solving for p, Initial residual = 0.003160602108, Final residual = 9.794177338e-07, No Iterations 69
DICPCG: Solving for p, Initial residual = 0.0004558492254, Final residual = 9.278622052e-07, No Iterations 58
diagonal: Solving for rho, Initial residual = 0, Final residual = 0, No Iterations 0 Solving for density (rhoFinal)
time step continuity errors : sum local = 6.38639685e-11, global = 1.446434866e-12, cumulative = 2.368221232e-09
rho max/min : 1.201420288 1.201381976 Max/min density values
ExecutionTime = 480.88 s ClockTime = 490 s
266
Flow past a cylinder – From laminar to turbulent flow
• This is what you will find in each directory,
• c19 = blockMesh – pimpleFoam – Unsteady solver – Re = 1000000 – Spalart Allmaras turbulent model no wall functions.
• c20 = blockMesh – rhoPimpleFoam – Unsteady solver – Mach = 2.0 – Compressible – Laminar.
• c21 = blockMesh – rhoPimpleFoam –Unsteady solver – Mach = 2.0 – Unsteady solver – Compressible – K-Omega SST
turbulent model with wall functions.
• c22 = blockMesh – rhoSimpleFoam – Mach = 2.0 – Steady solver – Compressible – K-Omega SST turbulent model with
wall functions.
• c23 = blockMesh – rhoPimpleFoam – Mach = 2.0 – LTS Pseudo-transient solver – Compressible – K-Omega SST
turbulent model with wall functions.
• c24 = blockMesh – pimpleFoam – Unsteady solver – Re = 200 – No turbulent model – Source terms (momentum)
• c25 = blockMesh – pimpleFoam – Unsteady solver – Re = 200 – No turbulent model – Source terms (scalar transport)
• c26 = blockMesh – rhoPimpleFoam – Unsteady solver – Re = 200 – Laminar, isothermal
• c27 = blockMesh – rhoPimpleFoam – Unsteady solver – Re = 20000 – Turbulent, compressible
• c28 = blockMesh – pimpleDyMFoam – Unsteady solver – Re = 200 – Laminar, moving cylinder (oscillating).
• c29 = blockMesh – pimpleDyMFoam/pimpleFoam – Unsteady solver – Re = 200 – Laminar, rotating cylinder using AMI
patches.
• c30 = blockMesh – interFoam – Unsteady solver – Laminar, multiphase, free surface.
• c31 = blockMesh – pimpleFoam – Unsteady solver – Laminar with source terms and AMR.
267
Module 2
Solid modeling
268
Roadmap
269
Solid modeling – Preliminaries
• There is no wrong or right way when doing solid modeling for CFD. The
only rule you should keep in mind is that by the end of the day you should
get a smooth, clean, and watertight geometry.
• A watertight geometry means a close body with no holes or overlapping
surfaces.
• Have in mind that the quality of the mesh and hence of the solution, greatly
depends on the geometry. So always do your best when creating the
geometry.
• During this solid modeling session we are going to show you how to get
started with the geometry generation tools. The rest is on you.
• The best way to learn how to use these tools is by doing.
• The tool of our choice is Onshape (www.onshape.com). However, have in
mind that all CAD and solid modeling applications have similar capabilities.
270
Solid modeling – Preliminaries
• There are always many ways to accomplish a task when creating a
geometry, this give you the freedom to work in a way that is comfortable to
you. Hereafter we are going to show you our way.
• Before starting to create your geometry, think about a strategy to employ to
create your design, this is what we call design intent.
• Choose one feature over other.
• Dimensioning strategy.
• Order of the operations.
• Parametrization.
• Single or multiple parts.
• Do I need to parametrize my design, or should I use direct
modeling?
• We are going to work with design intent during the hands-on sessions.
271
Solid modeling – Preliminaries
Geometry defeaturing
• Many times, it is not necessary to model all the details of the geometry. In these cases you
should consider simplifying the geometry (geometry defeaturing).
• Geometry defeaturing can save you a lot of time when generating the mesh. So be smart,
and use it whenever is possible.
Do we really need to
capture the fillet details?
Do we need to
model the flange?
272
Solid modeling – Preliminaries
Geometry defeaturing
• Would you use all these geometry details for a CFD simulations?
273
Solid modeling using Onshape
• Onshape is a professional CAD/solid modeling application.
• It provides powerful parametric and direct modeling capabilities.
• It is cloud based therefore you do not need to install any software.
• Documents are shareable.
• Multiple users can work in the same document at the same time
(simultaneous editing).
• It runs in any device with a working web browser.
• Users can implement their own features using Onshape scripting language
(featureScript).
• Users can access and modify documents in a programmatic way using
python or nodejs.
• It is freely available for educational use and personal use.
• To start using Onshape register at: https://cad.onshape.com/
274
Solid modeling using Onshape
• Even if you have not used a CAD software before, you will find the GUI easy to use.
• You will notice that there is no save button because everything you do is
automatically saved.
Help
Versioning, branching, and history menu Toolbar
Feature list
Parts list
3D area
Document tabs 275
Solid modeling using Onshape
• Mouse interaction in the 3D area (it can be configured in the preference area).
Selection
Rotate
Pan
Zoom
Feature toolbar:
Sketch toolbar:
277
Solid modeling using Onshape
• Let us create this solid using the dimensions illustrated.
279
Solid modeling using Onshape
• In the part studio page, select the top plane and start a new sketch.
280
Solid modeling using Onshape
• In the part studio page, select the top plane and start a new sketch.
281
Solid modeling using Onshape
• Using the sketching features, draw the following line.
When you are done sketching
press the checkmark
Origin
283
Solid modeling using Onshape
• Use the sweep feature to create a new solid.
Select the circle as the Select new solid Select the lines as the
face to sweep sweep patch
Sweep feature
284
Solid modeling using Onshape
• At this point, you should have this solid.
Solid name.
Right click to rename
or view the properties
285
Solid modeling using Onshape
• Let us add the new inlet to the pipe.
• Create a new sketch in the top plane or edit the initial sketch.
• Hereafter we will edit the initial sketch.
286
Solid modeling using Onshape
• Create a plane normal to a line and passing through a point
287
Solid modeling using Onshape
• Sketch a circle in the newly created plane.
New plane
288
Solid modeling using Onshape
• Using the feature extrude to create a new solid using the previous sketch.
• Extrude the circle until in intercept the solid.
Add the new solid to the previous part (boolean operation)
Feature extrusion
290
Solid modeling using Onshape
• If you want to know the mass properties of the solid, select it, and then click on the
mass properties icon.
• To get the inertia, you will need to assign a material.
291
Solid modeling using Onshape
• To export the solid model, right click on the part name and select the option export.
• Choose the desired format. In this case choose STL.
292
Solid modeling using Onshape
• Parametric modeling and feature-based modeling are two of the most powerful tools
available in any CAD/solid modeling applications.
• They are crucial components in the design experience, especially when dealing with
design intent.
• Experimenting with dimension schemes is one of the best ways to improve your
understanding of design intent.
• To learn more about Onshape, you can visit their learning center:
https://learn.onshape.com/
• Finally, feel free to visit our youtube channel where you will find a few solid modeling
videos in the context of CFD and OpenFOAM® :
https://www.youtube.com/channel/UCNNBm3KxVS1rGeCVUU1p61g
293
Solid modeling using Onshape
• At the following links, you can find a few geometries that you can use to setup cases
from scratch:
• Sailing boat:
https://cad.onshape.com/documents/ad885ed6298e6d95e372f573/w/1cfda457fe3ad410332aad9c/e/8dac4fcaf6e34a43e9676fbc
• Mixing elbow:
https://cad.onshape.com/documents/1cc919d8e75c2e47e8c1d50e/w/0efa002648eb2fb80ec4bec4/e/a742bf4113c626735e1d8f1a
• Static mixer:
https://cad.onshape.com/documents/58f7930861743e1074559ea6/w/96672317c9167265f9d10181/e/e4b6b1baffa90ca207afe974
• Ahmed body:
https://cad.onshape.com/documents/e1ecbacd95be9ed0962aa410/w/f0295899197e2f3d851000fd/e/aa40f8f5d26b7117dd0a5111
• Mixing tank:
https://cad.onshape.com/documents/e00307c191ce168d1d8c2e05/w/fc5d69b18559ec3893a1a80a/e/ba4b5ca5b34ad7335a2915a3
• Onera M6 wing:
https://cad.onshape.com/documents/e176caaa70bfd4719cafe3d7/w/9d8b5771d7382000b0762e65/e/ec4669f8c28761e60e35b32f
294
Module 3
Meshing preliminaries – Mesh quality
assessment – Meshing in OpenFOAM®
295
Before we begin
• OpenFOAM® comes with the following meshing applications:
• blockMesh
• snappyHexMesh
• foamyHexMesh
• foamyQuadMesh
• We are going to work with blockMesh and snappyHexMesh.
• blockMesh is a multi-block mesh generator.
• snappyHexMesh is an automatic split hex mesher, refines and snaps to surface.
• If you are not comfortable using OpenFOAM® meshing applications, you can use an
external mesher.
• OpenFOAM® comes with many mesh conversion utilities. Many popular meshing
formats are supported. To name a few: gambit, cfx, fluent, gmsh, ideas, netgen,
plot3d, starccm, VTK.
• In this module, we are going to address how to mesh using OpenFOAM®
technology, how to convert meshes to OpenFOAM® format, and how to assess
mesh quality in OpenFOAM®.
296
Before we begin
By the end of this module, you will realize that
You will use snappyHexMesh to mesh the sphinx
297
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
298
Meshing preliminaries
• Mesh generation or domain discretization consist in dividing the physical
domain into a finite number of discrete regions, called control volumes or
cells in which the solution is sought
www.wolfdynamics.com/wiki/moving/ani1.gif www.wolfdynamics.com/wiki/moving/ani2.gif
299
Meshing preliminaries
Mesh generation process
• Generally speaking, when generating the mesh we follow these three
simple steps:
• Geometry generation: we first generate the geometry that we are going
to feed into the meshing tool.
• Mesh generation: the mesh can be internal or external. We also define
surface and volume refinement regions. We can also add inflation layers
to better resolve the boundary layer. During the mesh generation
process we also check the mesh quality.
• Definition of boundary surfaces: in this step we define physical
surfaces where we are going to apply the boundary conditions. If you do
not define these individual surfaces, you will have one single surface
and it will not be possible to apply different boundary conditions.
300
Meshing preliminaries
Geometry generation - Input geometry
• The geometry must be watertight.
• Remember, the quality of the mesh and hence the quality of the solution greatly depends on the geometry. So
always do your best when creating the geometry.
301
Meshing preliminaries
Mesh generation
• If we are interested in external aerodynamics, we define a physical domain and we mesh the region around
the body.
• If we are interested in internal aerodynamics, we simply mesh the internal volume of the geometry.
• To resolve better the flow features, we can add surface and volume refinement.
• Remember to always check the mesh quality.
302
Meshing preliminaries
Definition of boundary surfaces (patches)
• In order to assign boundary conditions, we need to create boundary surfaces (patches) where we are going to
apply the boundary values.
• The boundary surfaces (patches) are created at meshing time.
• In OpenFOAM®, you will find this information in the boundary dictionary file which is located in the directory
constant/polyMesh. This dictionary is created automatically at meshing time.
inlet outlet
top
left right
airplane
bottom 303
Meshing preliminaries
What cell type should I use?
• In the meshing world, there are many cell types. Just to name a few: tetrahedrons,
pyramids, hexahedrons, prisms, polyhedral.
• Each cell type has its very own properties when it comes to approximate the gradients
and fluxes, we are going to talk about this later on when we deal with the FVM.
• Generally speaking, hexahedral cells will give more accurate solutions under certain
conditions.
• However, this does not mean that tetra/poly cells are not good.
• What cell type do I use? It is up to you; at the end of the day the overall quality of the
final mesh should be acceptable, and your mesh should resolve the physics
304
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
305
What is a good mesh?
• There is no written theory when it comes to mesh generation.
• Basically, the whole process depends on user experience and good standard
practices.
• A standard rule of thumb is that the elements shape and distribution should be
pleasing to the eye.
306
What is a good mesh?
• In a more sounded way, the user can rely in mesh metrics.
• However, no single standard benchmark or metric exists that can effectively
assess the quality of a mesh, but the user can rely on suggested best
practices.
• Hereafter, we will present the most common mesh quality metrics:
• Orthogonality.
• Skewness.
• Aspect Ratio.
• Smoothness.
• After generating the mesh, we measure these quality metrics to assess the
mesh quality.
• Have in mind that there are many more mesh quality metrics out there, and
some of them are not very easy to interpret (e.g., jacobian matrix,
determinant, flatness, equivalence, condition number, and so on).
• It seems that it is much easier diagnosing bad meshes than good meshes.
307
What is a good mesh?
Mesh quality metrics. Mesh orthogonality
• Mesh orthogonality is the angular deviation of the vector S (located at the face center
f ) from the vector d connecting the two cell centers P and N. In this case is .
• It mainly affects the Laplacian and gradient terms at the face center f.
• It adds numerical diffusion to the solution.
308
What is a good mesh?
Mesh quality metrics. Mesh skewness
• Skewness (also known as non-conjunctionality) is the deviation of the vector d that
connects the two cells P and N, from the face center f.
• The deviation vector is represented with and is the point where the vector d
intersects the face f .
• It affects the interpolation of the cell centered quantities at the face center f.
• It affects the computation of the convective, diffusive, and gradient terms.
• It adds numerical diffusion and wiggles to the solution.
309
What is a good mesh?
Mesh quality metrics. Mesh aspect ratio AR
• Mesh aspect ratio AR is the ratio between the longest side and the shortest
side .
• Large AR are ok if gradients in the largest direction are small.
• High AR smear gradients.
• Large AR can add numerical diffusion to the solution.
310
What is a good mesh?
Mesh quality metrics. Smoothness
• Smoothness, also known as expansion rate, growth factor or uniformity, defines the
transition in size between contiguous cells.
• Large transition ratios between cells add diffusion to the solution.
• Ideally, the maximum change in mesh spacing should be less than 20%:
• Hexes, prisms, and quadrilaterals can be stretched easily to resolve boundary layers
without losing quality.
• Triangular and tetrahedral meshes have inherently larger truncation error.
• Less truncation error when faces aligned with flow direction and gradients.
Flow direction
312
What is a good mesh?
Striving for quality
• For the same cell count, hexahedral meshes will give more accurate solutions,
especially if the grid lines are aligned with the flow.
• But this does not mean that tetrahedral meshes are not good, by carefully choosing
the numerical scheme you can get the same level of accuracy as in hexahedral
meshes.
• The problem with tetrahedral meshes is mainly related to the way gradients are
computed.
Hexa
Year 313
What is a good mesh?
Striving for quality
• The mesh density should be high enough to capture all relevant flow features.
• In areas where the solution change slowly, you can use larger elements.
• A good mesh does not rely in the fact that the more cells we use the better the
solution.
315
What is a good mesh?
Striving for quality
• Use hexahedral meshes whenever is possible, specially if high accuracy in predicting forces is
your goal (drag prediction) or for turbo machinery applications.
• For complex flows without dominant flow direction, quad and hex meshes loose their
advantages.
• Keep orthogonality, skewness, and aspect ratio to a minimum.
• Change in cell size should be smooth.
• Always check the mesh quality. Remember, one single cell can cause divergence or give you
inaccurate results.
• When you strive for quality, you avoid the GIGO syndrome (garbage in, garbage out).
• Just to end for good the mesh quality talk:
• A good mesh is a mesh that serves your project objectives.
• So, as long as your results are physically realistic, reliable and accurate; your mesh is
good.
• Know your physics and generate a mesh able to resolve the physics involve, without
over-doing.
316
What is a good mesh?
A good mesh might not lead to the ideal solution, but a bad
mesh will always lead to a bad solution.
P. Baker – Pointwise
317
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
318
Mesh quality assessment in OpenFOAM®
Mesh quality metrics in OpenFOAM®
• In the file primitiveMeshCheck.C located in the directory
$WM_PROJECT_DIR/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/ you will find the
quality metrics hardwired in OpenFOAM®. Their maximum (or minimum) values are defined as follows:
• You will be able to run simulations with mesh quality errors such as high skewness, high aspect ratio, and high
non-orthogonality. But remember, they will affect the solution accuracy, might give you strange results, and
eventually can made the solver blow-up.
• Have in mind that if you have bad quality meshes, you will need to adapt the numerics to deal with this kind of
meshes. We will give you our recipe later when we deal with the numerics.
• You should avoid as much as possible non-orthogonality values close to 90. This is an indication that you have
zero-volume cells.
• In overall, large aspect ratios do not represent a problem. It is just an indication that you have very fine
meshes (which is the case when you are resolving the boundary layer).
• The default quality metrics in OpenFOAM® seems to be a little bit conservative. In our experience, we have
found that you can run simulations with no numerical tricks with a non-orthogonality values up to 80 and
skewness values up to 8. 319
Mesh quality assessment in OpenFOAM®
Checking the mesh quality in OpenFOAM®
• To check the mesh quality and validity, OpenFOAM® comes with the utility checkMesh.
• To use this utility, just type in the terminal checkMesh, and read the screen output.
• checkMesh will look for/check for:
• Mesh stats and overall number of cells of each type.
• Check topology (boundary conditions definitions).
• Check geometry and mesh quality (bounding box, cell volumes, skewness, orthogonality, aspect
ratio, and so on).
• If for any reason checkMesh finds errors, it will give you a message and it will tell you what check failed.
• It will also write a set with the faulty cells, faces, and/or points.
• These sets are saved in the directory constant/polyMesh/sets/
• Mesh topology and patch topology errors must be repaired.
• You will be able to run with mesh quality errors such as skewness, aspect ratio, minimum face area, and non-
orthogonality.
• But remember, they will severely tamper the solution accuracy, might give you strange results, and eventually
can made the solver blow-up.
• Unfortunately, checkMesh does not repair these errors.
• You will need to check the geometry for possible errors and generate a new mesh.
• You can visualize the failed sets directly in paraFoam .
• You can also convert the failed sets into VTK format by using the utility foamToVTK.
320
Mesh quality assessment in OpenFOAM®
Visualizing the failed sets in OpenFOAM®
Check this box to include sets
• You can load the failed sets directly within
paraFoam.
• Remember, you will need to create the sets. To
do so, just run the checkMesh utility.
• If there are problems in the mesh, checkMesh
will automatically save the sets in the directory
constant/polyMesh/sets
• In paraFoam, simply select the option Include
Sets and then select the sets you want to
visualize.
• This method only works when using the wrapper
paraFoam.
• If you are using paraview or a different scientific
visualization application, you will need to convert
the failed sets to VTK format or an alternative
format.
• Also, when working with large meshes we prefer
to convert the faulty sets to VTK format.
• To convert the faulty sets to VTK format you can Failed sets
use the utility foamToVTK.
321
Mesh quality assessment in OpenFOAM®
Visualizing the failed sets in OpenFOAM®
• To convert the failed faces/cells/points to VTK format, you can proceed as follows:
where set_type is the type of sets (faceSet, cellSet, pointSet, surfaceFields) and
name_of_sets is the name of the set located in the directory
constant/polyMesh/sets (highAspectRatioCells, nonOrthoFaces,
wrongOrientedFaces, skewFaces, unusedPoints, and so on).
• At the end, foamToVTK will create a directory named VTK, where you will find the
failed faces/cells/points in VTK format.
• At this point you can use paraview/paraFoam or any scientific visualization
application to open the VTK files and visualize the failed sets.
322
Mesh quality assessment in OpenFOAM®
Checking mesh quality in OpenFOAM®
• Sample checkMesh output,
Mesh stats
points: 81812
faces: 902132
internal faces: 871012
cells: 443286
faces per cell: 4 Mesh stats
boundary patches: 9
point zones: 0
face zones: 1
cell zones: 1
Checking topology...
Boundary definition OK. Checking mesh topology
Cell to face addressing OK.
***Unused points found in the mesh, number unused by faces: 16 number unused by cells: 16
<<Writing 16 unused points to set unusedPoints
Upper triangular ordering OK.
Face vertices OK.
Number of regions: 1 (OK). Unused points found in the mesh
In this case they do not harm the solution
They can be removed using topoSet and subsetMesh
323
Mesh quality assessment in OpenFOAM®
Checking mesh quality in OpenFOAM®
• Sample checkMesh output,
Checking patch topology for multiply connected surfaces...
Patch Faces Points Surface topology
FAIRING 1267 727 ok (non-closed singly connected)
FUSELAGE 3243 1774 ok (non-closed singly connected)
WING 15313 7706 ok (non-closed singly connected)
INLET 272 160 ok (non-closed singly connected)
OUTLET 272 160 ok (non-closed singly connected) Boundary patches
SYMM 6280 3324 ok (non-closed singly connected)
FARFIELD 3136 1645 ok (non-closed singly connected)
NOSE 76 49 ok (non-closed singly connected)
COCKPIT 1261 670 ok (non-closed singly connected)
Checking geometry...
Overall domain bounding box (-15000 -7621.0713 -7396.4536) (30048.969 0 7446.8442)
Mesh has 3 geometric (non-empty/wedge) directions (1 1 1)
Mesh has 3 solution (non-empty) directions (1 1 1)
Mesh bounding box
Boundary openness (-4.2298633e-18 8.0240802e-16 4.013988e-16) OK.
Max cell openness = 4.8098963e-16 OK.
Max aspect ratio = 29.575835 OK. Aspect ratio
Minimum face area = 0.0066721253. Maximum face area = 1037224.8. Face area magnitudes OK.
Min volume = 0.00050536842. Max volume = 3.2500889e+08. Total volume = 5.0960139e+12. Cell volumes OK.
Mesh non-orthogonality Max: 86.939754 average: 17.939523 High non-orthogonality
*Number of severely non-orthogonal (> 70 degrees) faces: 3168. But we still can run the simulation
Non-orthogonality check OK.
<<Writing 3168 non-orthogonal faces to set nonOrthoFaces
Face pyramids OK.
Max skewness = 2.5719979 OK. Skewness
Coupled point location match (average 0) OK.
Failed 1 mesh checks. The fact that one check failed does not mean that you can not run the simulation
End 324
Mesh quality assessment in OpenFOAM®
Visualization of faulty sets in paraFoam
• You will find this case ready to use in the directory,
$PTOFC/mesh_quality_manipulation/M1_wingbody
• To run the case, just follow the instructions in the README.FIRST files.
Non orthogonal faces (green spheres) and unused points (yellow spheres) 325
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
326
Mesh generation using blockMesh
blockMesh
• “blockMesh is a multi-block mesh generator.”
• For simple geometries, the mesh generation utility blockMesh can be used.
• The mesh is generated from a dictionary file named blockMeshDict
located in the system directory.
• This meshing tool generates high quality meshes.
• It is the tool to use for very simple geometries. As the complexity of the
geometry increases, the effort and time required to setup the dictionary
increases a lot.
• Usually, the background mesh used with snappyHexMesh consist of a
single rectangular block; therefore, blockMesh can be used with no
problem.
• It is highly recommended to create a template of the dictionary
blockMeshDict that you can change according to the dimensions of your
domain.
• You can also use m4 or Python scripting to automate the whole process. 327
Mesh generation using blockMesh
blockMesh
• These are a few meshes that you can generate using blockMesh.
• As you can see, they are not very complex.
• However, generating the blocking topology requires some effort.
328
Mesh generation using blockMesh
blockMesh workflow
• To generate a mesh with blockMesh, you will need to define the vertices, block
connectivity and number of cells in each direction.
• To assign boundary patches, you will need to define the faces connectivity
329
blockMesh guided tutorials
$PTOFC/101BLOCKMESH/C1
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
330
blockMesh guided tutorials
What are we going to do?
• We will use this simple case to take a close look at a blockMeshDict dictionary.
• We will study all sections in the blockMeshDict dictionary.
• We will introduce two features useful for parameterization, namely, macro syntax and
inline calculations.
• You can use this dictionary as a blockMeshDict template that you can change
automatically according to the dimensions of your domain and the desired cell
spacing.
331
blockMesh guided tutorials
The blockMeshDict dictionary.
• The keyword convertToMeters (line 17), is a scaling
17 convertToMeters 1; factor. In this case we do not scale the dimensions.
18
19 xmin 0;
20 xmax 1; • In lines 19-24 we declare some variables using macro
21
22
ymin
ymax
0;
1;
syntax notation. With macro syntax, we first declare the
23 zmin 0; variables and their values (lines 19-24), and then we can
24 zmax 1;
25
use the variables by adding the symbol $ to the variable
30 deltax 0.05; name (lines 47-54).
31 deltay 0.05;
32 deltaz 0.05;
33 • In lines 30-32 we use macro syntax to declare another
34 lx #calc "$xmax - $xmin"; set of variables that will be used later.
35 ly #calc "$ymax - $ymin";
36 lz #calc "$zmax – $zmin";
37 • Macro syntax is a very convenient way to parameterize
38
39
xcells #calc "round(($lx)/($deltax))";
ycells #calc "round(($ly)/($deltay))";
dictionaries.
40 zcells #calc "round(($lz)/($deltaz))";
41
44 vertices
45 (
46 //BLOCK 0
47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7
66 );
332
blockMesh guided tutorials
The blockMeshDict dictionary.
• In lines 34-40 we are doing inline calculations using the
17 convertToMeters 1; directive #calc.
18
19 xmin 0;
20 xmax 1; • Basically we are programming directly in the dictionary.
21
22
ymin
ymax
0;
1;
OpenFOAM® will compile this function as it reads it.
23 zmin 0;
24 zmax 1; • With inline calculations and codeStream you can access
25
30 deltax 0.05;
many OpenFOAM® functions from the dictionaries.
31 deltay 0.05;
32 deltaz 0.05; • Inline calculations and codeStream are very convenient
33
34 lx #calc "$xmax - $xmin";
ways to parameterize dictionaries and program directly
35 ly #calc "$ymax - $ymin"; on the dictionaries.
36 lz #calc "$zmax – $zmin";
37
38 xcells #calc "round(($lx)/($deltax))";
39 ycells #calc "round(($ly)/($deltay))";
40 zcells #calc "round(($lz)/($deltaz))";
41
44 vertices
45 (
46 //BLOCK 0
47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7
66 );
333
blockMesh guided tutorials
The blockMeshDict dictionary.
• To do inline calculations using the directive #calc, we
17 convertToMeters 1; proceed as follows (we will use line 35 as example):
18
19 xmin 0;
20 xmax 1;
21 ymin 0;
22 ymax 1; ly #calc "$ymax - $ymin";
23 zmin 0;
24 zmax 1;
25
30 deltax 0.05;
31 deltay 0.05; • We first give a name to the new variable (ly), we then tell
32 deltaz 0.05;
33
OpenFOAM® that we want to do an inline calculation
34 lx #calc "$xmax - $xmin"; (#calc), and then we do the inline calculation ("$ymax-
35 ly #calc "$ymax - $ymin";
36 lz #calc "$zmax – $zmin"; $ymin";). Notice that the operation must be between
37
38 xcells #calc "round(($lx)/($deltax))";
double quotation marks.
39 ycells #calc "round(($ly)/($deltay))";
40 zcells #calc "round(($lz)/($deltaz))";
41
44 vertices
45 (
46 //BLOCK 0
47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7
66 );
334
blockMesh guided tutorials
The blockMeshDict dictionary.
• In lines lines 34-36, we use inline calculations to
17 convertToMeters 1; compute the length in each direction.
18
19 xmin 0;
20 xmax 1; • Then we compute the number of cells to be used in each
21
22
ymin
ymax
0;
1;
direction (lines 38-40).
23 zmin 0;
24 zmax 1; • To compute the number of cells we use as cell spacing
25
30 deltax 0.05;
the values declared in lines 30-32.
31 deltay 0.05;
32 deltaz 0.05; • By proceeding in this way, we can compute automatically
33
34 lx #calc "$xmax - $xmin";
the number of cells needed in each direction according to
35 ly #calc "$ymax - $ymin"; the desired cell spacing.
36 lz #calc "$zmax – $zmin";
37
38 xcells #calc "round(($lx)/($deltax))";
39 ycells #calc "round(($ly)/($deltay))";
40 zcells #calc "round(($lz)/($deltaz))";
41
44 vertices
45 (
46 //BLOCK 0
47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7
66 );
335
blockMesh guided tutorials
The blockMeshDict dictionary.
• In the vertices section (lines 44-66), we define the vertex
17 convertToMeters 1; coordinates of the geometry.
18
19 xmin 0;
20 xmax 1; • In this case, there are eight vertices defining a 3D block.
21 ymin 0;
22 ymax 1; • Remember, OpenFOAM® always uses 3D meshes, even
23 zmin 0;
24 zmax 1; if the simulation is 2D. For 2D meshes, you only add one
25
30 deltax 0.05;
cell in the third dimension.
31 deltay 0.05;
32 deltaz 0.05; • Notice that the vertex numbering starts from 0 (as the
33
34 lx #calc "$xmax - $xmin";
counters in c++). This numbering applies for blocks as
35 ly #calc "$ymax - $ymin"; well.
36 lz #calc "$zmax – $zmin";
37
38 xcells #calc "round(($lx)/($deltax))";
39 ycells #calc "round(($ly)/($deltay))";
40 zcells #calc "round(($lz)/($deltaz))";
41
44 vertices
45 (
46 //BLOCK 0
47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7
66 );
336
blockMesh guided tutorials
The blockMeshDict dictionary.
• In lines 68-71, we define the block topology, hex means that it is a structured hexahedral block. In this case,
we are generating a rectangular mesh.
• In line 70, (0 1 2 3 4 5 6 7) are the vertices used to define the block (and yes, the order is important). Each
hex block is defined by eight vertices, in sequential order. Where the first vertex in the list represents the
origin of the coordinate system (vertex 0 in this case).
• ($xcells $ycells $zcells) is the number of mesh cells in each direction (X Y Z). Notice that we are using
macro syntax, and we compute the values using inline calculations.
• simpleGrading (1 1 1) is the grading or mesh stretching in each direction (X Y Z), in this case the mesh is
uniform. We will deal with mesh grading/stretching in the next case.
68 blocks
69 (
70 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
71 );
72
73 edges
74 (
75
76 );
337
blockMesh guided tutorials
The blockMeshDict dictionary.
• Let us talk about the block ordering hex (0 1 2 3 4 5 6 7), which is extremely important.
• hex blocks are defined by eight vertices in sequential order. Where the first vertex in the list represents the
origin of the coordinate system (vertex 0 in this case).
• Starting from this vertex, we construct the block topology. So in this case, the first part of the block is made up
by vertices 0 1 2 3 and the second part of the block is made up by vertices 4 5 6 7 (notice that we start from
vertex 4 which is the projection in the Z-direction of vertex 0).
• In this case, the vertices are ordered in such a way that if we look at the screen/paper (-z direction), the
vertices rotate counter-clockwise.
• If you add a second block, you must identify the first vertex and starting from it, you should construct the block
topology. In this case, you will need to merges faces, you will find more information about merging face in the
supplement lectures.
68 blocks
69 (
70 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
71 );
72
73 edges
74 (
75
76 );
338
blockMesh guided tutorials
The blockMeshDict dictionary.
• Edges, are constructed from the vertices definition.
• Each edge joining two vertices is assumed to be straight by default.
• The user can specify any edge to be curved by entries in the section edges.
• Possible options are Bspline, arc, line, polyline, project, projectCurve, spline.
• For example, to define an arc we first define the vertices to be connected to form an edge and then we give an
interpolation point.
• To define a polyline we first define the vertices to be connected to form an edge and then we give a list of the
coordinates of the interpolation points.
• In this case and as we do not specify anything, all edges are assumed to be straight lines.
68 blocks
69 (
70 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
71 );
72
73 edges
74 (
75
76 );
339
blockMesh guided tutorials
The blockMeshDict dictionary.
• In the section boundary, we define all the patches where
78 boundary we want to apply boundary conditions.
79 (
80 top
81 { • This step is of paramount importance, because if we do
82
83
type wall;
faces
not define the surface patches, we will not be able to
84 ( apply the boundary conditions to individual surface
85 (3 7 6 2)
86 );
patches.
87 }
88 left
89 {
90 type wall;
91 faces
92 (
93 (0 4 7 3)
94 );
95 }
96 right
97 {
98 type wall;
99 faces
100 (
101 (2 6 5 1)
102 );
103 }
104 bottom
105 {
106 type wall;
107 faces
108 (
109 (0 1 5 4)
110 );
111 }
340
blockMesh guided tutorials
The blockMeshDict dictionary.
• In lines 80-87 we define a boundary patch.
78 boundary
79 ( • In line 80 we define the patch name top (the name is
80 top
81 { given by the user).
82 type wall;
83 faces • In line 82 we give a base type to the surface patch. In
84 (
85 (3 7 6 2) this case wall (do not worry we are going to talk about
86
87 }
); this later).
88 left
89 { • In line 85 we give the connectivity list of the vertices that
90
91
type wall;
faces
made up the surface patch or face, that is, (3 7 6 2).
92 (
93 (0 4 7 3) • Have in mind that the vertices need to be neighbors and
94
95 }
);
it does not matter if the ordering is clockwise or
96 right counterclockwise.
97 {
98 type wall;
99 faces
100 (
101 (2 6 5 1)
102 );
103 }
104 bottom
105 {
106 type wall;
107 faces
108 (
109 (0 1 5 4)
110 );
111 }
341
blockMesh guided tutorials
The blockMeshDict dictionary.
• Have in mind that the vertices need to be neighbors and
78 boundary it does not matter if the ordering is clockwise or
79 (
80 top counterclockwise.
81 {
82
83
type wall;
faces
• Remember, faces are defined by a list of 4 vertex
84 ( numbers, e.g., (3 7 6 2).
85 (3 7 6 2)
86
87 }
); • In lines 88-95 we define the patch left.
88 left
89 { • In lines 96-103 we define the patch right.
90 type wall;
91 faces • In lines 104-11 we define the patch bottom.
92 (
93 (0 4 7 3)
94 );
95 }
96 right
97 {
98 type wall;
99 faces
100 (
101 (2 6 5 1)
102 );
103 }
104 bottom
105 {
106 type wall;
107 faces
108 (
109 (0 1 5 4)
110 );
111 }
342
blockMesh guided tutorials
The blockMeshDict dictionary.
• In lines 112-119 we define the patch front.
112 front
113 { • In lines 120-127 we define the patch back.
114 type wall;
115
116
faces
(
• You can also group many faces into one patch, for
117 (4 5 6 7) example, instead of creating the patches front and back,
118 );
119 } you can group them into a single patch named
120
121
back
{
backAndFront, as follows,
122 type wall;
123 faces
124 (
125 (0 3 2 1) backAndFront
126 ); {
127 }
128 ); type wall;
129 faces
130 mergePatchPairs
131 ( (
132 (4 5 6 7)
133 );
(0 3 2 1)
);
}
343
blockMesh guided tutorials
The blockMeshDict dictionary.
• We can merge blocks in the section mergePatchPairs
112 front (lines 130-133).
113 {
114 type wall;
115 faces • The block patches to be merged must be first defined in
116 ( the boundary list, blockMesh then connect the two
117 (4 5 6 7)
118 ); blocks.
119 }
120
121
back
{
• In this case, as we have one single block there is no
122 type wall; need to merge patches.
123 faces
124 (
125 (0 3 2 1)
126 );
127 }
128 );
129
130 mergePatchPairs
131 (
132
133 );
344
blockMesh guided tutorials
The blockMeshDict dictionary.
345
blockMesh guided tutorials
The constant/polyMesh/boundary dictionary
18
19
6
(
• First of all, this file is automatically generated after you
20 top create the mesh or you convert it from a third-party format.
21 {
22 type wall;
23 inGroups 1(wall); • In this file, the geometrical information related to the base
24 nFaces 400;
25 startFace 22800; type patch of each boundary of the domain is specified.
26 }
27 left
28 { • The base type boundary condition is the actual surface
29 type wall;
30 inGroups 1(wall); patch where we are going to apply a primitive type
31
32
nFaces
startFace
400;
23200;
boundary condition (or numerical boundary condition).
33 }
34
35
right
{
• The primitive type boundary condition assign a field value
36 type empty; to the surface patch.
37 inGroups 1(wall);
38 nFaces 400;
39 startFace 23600; • You define the numerical type patch (or the value of the
40 }
41 bottom boundary condition), in the directory 0 or time directories.
42 {
43 type wall;
44 inGroups 1(wall); • The name and base type of the patches was defined in the
45
46
nFaces
startFace
400;
24000;
dictionary blockMeshDict in the section boundary.
47 }
48 front
49 { • You can change the name if you do not like it. Do not use
50
51
type
inGroups
wall;
1(wall);
strange symbols or white spaces.
52 nFaces 400;
53
54 }
startFace 24400; • You can also change the base type. For instance, you can
55 back change the type of the patch top from wall to patch.
56 {
57 type empty;
58 inGroups 1(wall);
59 nFaces 400;
60 startFace 24800;
61 }
62 ) 346
blockMesh guided tutorials
The constant/polyMesh/boundary dictionary
18
19
6
(
• If you do not define the boundary patches in the dictionary
20 top blockMeshDict, they are grouped automatically in a default
21 {
22 type wall; group named defaultFaces of type empty.
23 inGroups 1(wall);
24
25
nFaces
startFace
400;
22800;
• For instance, if you do not assign a base type to the patch
26 } front, it will be grouped as follows:
27 left
28 {
29 type wall;
30 inGroups 1(wall);
31 nFaces 400;
defaultFaces
32 startFace 23200; {
33 } type empty;
34 right inGroups 1(empty);
35 {
36 type empty;
nFaces 400;
37 inGroups 1(wall); startFace 24800;
38 nFaces 400; }
39 startFace 23600;
40 }
41 bottom
42 {
43 type wall; • Remember, you can manually change the name and type.
44 inGroups 1(wall);
45 nFaces 400;
46 startFace 24000;
47 }
48 front
49 {
50 type wall;
51 inGroups 1(wall);
52 nFaces 400;
53 startFace 24400;
54 }
55 back
56 {
57 type empty;
58 inGroups 1(wall);
59 nFaces 400;
60 startFace 24800;
61 }
62 ) 347
blockMesh guided tutorials
The constant/polyMesh/boundary dictionary
18
19
6
(
Number of surface patches
20 top
21 {
22 type wall; In the list bellow there must be 6 patches
23 inGroups 1(wall);
24 nFaces 400; definition.
25 startFace 22800;
26 }
27 left
28 {
29 type wall;
30 inGroups 1(wall); top
31 nFaces 400;
32 startFace 23200;
33 }
34 right
35 {
36 type empty;
37 inGroups 1(wall); back
38 nFaces 400;
39 startFace 23600;
40 }
41 bottom
42 {
43 type wall;
44 inGroups 1(wall);
45 nFaces 400; left right
46 startFace 24000;
47 }
48 front
49 {
50 type wall;
51 inGroups 1(wall);
52 nFaces 400; front
53 startFace 24400;
54 }
55 back
56 {
57 type empty;
58 inGroups 1(wall);
59 nFaces 400; bottom
60 startFace 24800;
61 }
62 ) 348
blockMesh guided tutorials
The constant/polyMesh/boundary dictionary
18 6
19 (
20 top
21 {
22 type wall; Name and type of the surface patches
23 inGroups 1(wall);
24 nFaces 400;
25 startFace 22800;
26 } • The name and base type of the patch is given
27 left
28 { by the user.
29 type wall;
30
31
inGroups
nFaces
1(wall);
400;
• In this case the name and base type was
32 startFace 23200; assigned in the dictionary blockMeshDict.
33 }
34 right
35 { • You can change the name if you do not like it.
36
37
type
inGroups
wall;
1(wall);
Do not use strange symbols or white spaces.
38 nFaces 400;
39 startFace 23600; • You can also change the base type. For
40 }
41 bottom instance, you can change the type of the
42
43
{
type wall;
patch top from wall to patch.
44 inGroups 1(wall);
45 nFaces 400;
46 startFace 24000;
47 }
48 front
49 {
50 type wall;
51 inGroups 1(wall);
52 nFaces 400;
53 startFace 24400;
54 }
55 back
56 {
57 type wall;
58 inGroups 1(wall);
59 nFaces 400;
60 startFace 24800;
61 }
62 ) 349
blockMesh guided tutorials
The constant/polyMesh/boundary dictionary
18 6
19 (
20 top
21 {
22 type wall; inGroups keyword
23 inGroups 1(wall);
24 nFaces 400;
25 startFace 22800;
26 } • This is optional.
27 left
28
29
{
type wall; • You can erase this information safely.
30 inGroups 1(wall);
31 nFaces 400; • It is used to group patches during visualization
32 startFace 23200;
33 } in ParaView/paraFoam. If you open this mesh
34 right
35 { in paraFoam you will see that there are two
36
37
type
inGroups
wall;
1(wall);
groups, namely: wall and empty.
38 nFaces 400;
39 startFace 23600; • As usual, you can change the name.
40 }
41
42
bottom
{ • If you want to put a surface patch in two
43
44
type
inGroups
wall;
1(wall);
groups, you can proceed as follows:
45 nFaces 400;
46 startFace 24000; 2(wall wall1)
47 }
48
49
front
{
In this case the surface patch belongs to the
50
51
type
inGroups
wall;
1(wall);
group wall (which can have another patch)
52 nFaces 400; and the group wall1
53 startFace 24400;
54 }
55 back
56 {
57 type wall;
58 inGroups 1(wall);
59 nFaces 400;
60 startFace 24800;
61 }
62 ) 350
blockMesh guided tutorials
The constant/polyMesh/boundary dictionary
18 6
19 (
20 top
21 {
22 type wall; nFaces and startFace keywords
23 inGroups 1(wall);
24 nFaces 400;
25 startFace 22800;
26 } • Unless you know what are you doing, you do
27 left
28 { not need to change this information.
29 type wall;
30
31
inGroups
nFaces
1(wall);
400;
• Basically, this is telling you the starting face
32 startFace 23200; and ending face of the patch.
33 }
34 right
35 { • This information is created automatically when
36
37
type
inGroups
wall;
1(wall);
generating the mesh or converting the mesh.
38 nFaces 400;
39 startFace 23600;
40 }
41 bottom
42 {
43 type wall;
44 inGroups 1(wall);
45 nFaces 400;
46 startFace 24000;
47 }
48 front
49 {
50 type wall;
51 inGroups 1(wall);
52 nFaces 400;
53 startFace 24400;
54 }
55 back
56 {
57 type wall;
58 inGroups 1(wall);
59 nFaces 400;
60 startFace 24800;
61 }
62 ) 351
blockMesh guided tutorials
Running the case
1. $> foamCleanTutorials
2. $> blockMesh
3. $> checkMesh
4. $> paraFoam
• You can run the rest of the cases following the same steps.
352
blockMesh guided tutorials
Final remarks on blockMesh
• For the moment, we will limit the use of blockMesh to single-block mesh topologies, which are
used to run some simple cases and are the starting point for snappyHexMesh.
• But have in mind that you can do more elaborated meshes, however, it requires careful setup of
the input dictionary.
• Have in mind that it can be really tricky to generate multi-block meshes with curve edges.
• With the training material, you will find a set of supplement slides where we explain how to
create multi-block meshes, add stretching, and how to define curve edges.
Single-block mesh with multi-stretching Multi-block mesh with curved edges and Multi-block mesh with face merging
multi-stretching
353
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
354
Mesh generation using snappyHexMesh
snappyHexMesh
• “Automatic split hex mesher. Refines and snaps to surface.”
• For complex geometries, the mesh generation utility snappyHexMesh can be used.
• The snappyHexMesh utility generates 3D meshes containing hexahedra and split-
hexahedra from a triangulated surface geometry in Stereolithography (STL) format.
• The mesh is generated from a dictionary file named snappyHexMeshDict located in
the system directory and a triangulated surface geometry file located in the directory
constant/triSurface.
355
Mesh generation using snappyHexMesh
snappyHexMesh workflow
• To generate a mesh with snappyHexMesh we proceed as follows:
• Generation of a background or base mesh.
• Geometry definition.
• Generation of a castellated mesh or cartesian mesh.
• Generation of a snapped mesh or body fitted mesh.
• Addition of layers close to the surfaces or boundary layer meshing.
• Check/enforce mesh quality.
snappyHexMesh
OpenFOAM mesh
356
Mesh generation using snappyHexMesh
snappyHexMesh workflow – Background mesh
• The background or base mesh can be generated using blockMesh or an
external mesher.
• The following criteria must be observed when creating the background
mesh:
• The mesh must consist purely of hexes.
• The cell aspect ratio should be approximately 1, at least near the
STL surface.
• There must be at least one intersection of a cell edge with the
STL surface.
blockMesh or external mesher
snappyHexMesh
OpenFOAM mesh
357
Mesh generation using snappyHexMesh
snappyHexMesh workflow – Geometry (STL file)
• The STL geometry can be obtained from any geometry modeling tool.
• The STL file can be made up of a single surface describing the geometry, or
multiple surfaces that describe the geometry.
• In the case of a STL file with multiple surfaces, we can use local refinement
in each individual surface. This gives us more control when generating the
mesh.
• The STL geometry is always located in the directory
constant/triSurface
snappyHexMesh
OpenFOAM mesh
358
Mesh generation using snappyHexMesh
snappyHexMesh workflow
• The meshing utility snappyHexMesh reads the dictionary
snappyHexMeshDict located in the directory system.
• The castellation, snapping, and boundary layer meshing steps are controlled
by the dictionary snappyHexMeshDict.
• The final mesh is always located in the directory
constant/polyMesh
snappyHexMesh
OpenFOAM mesh
359
Mesh generation using snappyHexMesh
snappyHexMesh workflow
• All the volume and surface refinement is done in reference to the
background or base mesh.
and so on …
Base cell – RL 0 RL 1 RL 2
* RL = refinement level
Note:
• In 2D each quad is subdivided in 4
quads.
• In 3D each hex is subdivided in 8
hexes.
360
Mesh generation using snappyHexMesh
snappyHexMesh workflow
• The process of generating a mesh using snappyHexMesh will be described using this figure.
• The objective is to mesh a rectangular shaped region (shaded grey in the figure) surrounding an object
described by a STL surface (shaded green in the figure).
• This is an external mesh (e.g. for external aerodynamics).
• You can also generate an internal mesh (e.g. flow inside a pipe). 361
Mesh generation using snappyHexMesh
snappyHexMesh workflow
363
Mesh generation using snappyHexMesh
snappyHexMesh workflow
364
Mesh generation using snappyHexMesh
snappyHexMesh workflow
365
Mesh generation using snappyHexMesh
snappyHexMesh workflow
366
Mesh generation using snappyHexMesh
snappyHexMesh workflow
369
Mesh generation using snappyHexMesh
$PTOFC/101SHM/M101_WD
370
Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.
castellatedMesh true; //or false • Have in mind that there are more than 70
snap true; //or false
addLayers true; //or false parameters to control in
snappyHexMeshDict dictionary.
geometry
{
... • Adding the fact that there is no native GUI, it
... can be quite tricky to control the mesh
}
generation process.
castellatedMeshControls
{
... • Nevertheless, snappyHexMesh generates
...
} very good hexa dominant meshes.
snapControls
{ • Hereafter, we will only comment on the most
...
...
important parameters.
}
regions Use this option if you have a STL with multiple patches defined
{
wolflocal This is the name of the region or surface patch in the STL
{
name wolf_wall; User-defined patch name. This is the final name of the patch
}
}
}
• In this section we read in the STL geometry. Remember, the input
box Name of geometrical entity
geometry is always located in the directory constant/triSurface
{
type searchableBox; • We can also define geometrical entities that can be used to refine the
min (-100.0 -120.0 -50.0 ); mesh, create regions, or generate baffles.
max (100.0 120.0 150.0 );
} • You can add multiple STL files.
sphere Name of geometrical entity • If you do not give a name to the surface, it will take the name of the
{ STL file.
type searchableSphere; Note 1
centre (120.0 -100.0 50.0 ); • The geometrical entities are created inside snappyHexMesh.
radius 40.0;
} Note 1:
If you want to know what geometrical entities are available, just
} misspelled something in the type keyword.
373
Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.
Castellated mesh controls section
castellatedMeshControls
{
//Refinement parameters
maxLocalCells 100000;
maxGlobalCells 2000000; Note 1
nCellsBetweenLevels 3;
...
...
// Refinement parameters
maxLocalCells 100000;
maxGlobalCells 2000000;
minRefinementCells 0;
maxLoadUnbalance 0.10;
nCellsBetweenLevels 3; Note 1
planarAngle 30;
allowFreeStandingZoneFaces true;
...
...
...
regions Note 2
{
wolflocal Note 3
Note 1:
{
The surface wolf was defined in the geometry section.
level (2 4); Local refinement
Note 2:
patchInfo
The region wolflocal was defined in the geometry section.
{
type wall; Note 4
Note 3:
}
Named region in the STL file. This refinement is local.
}
To use the surface refinement in the regions, the local
}
regions must exist in STL file. We created a pointer to this
}
region in the geometry section.
...
...
Note 4:
} 376
You can only define patches of type wall or patch.
Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.
Castellated mesh controls section
castellatedMeshControls
{
...
...
...
//This surface or geometrical entity
//was defined in geometry section
sphere Note 1
{
level (1 1);
Name of faceZone
faceZone face_inner;
cellZone cell_inner; Name of cellZone
...
...
...
//Region-wise refinement
refinementRegions Dictionary block
{
box Note 1
{
mode inside;
levels (( 1 1 ));
}
378
Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.
Castellated mesh controls section
castellatedMeshControls
{
...
...
...
//Region-wise refinement
refinementRegions Dictionary block
{
box
{
mode inside;
levels (( 1 1 ));
}
}
This point defines where do you want the mesh.
Can be internal mesh or external mesh.
//Mesh selection
locationInMesh (-100.0 0.0 50.0 ); • If the point is inside the STL it is an internal mesh.
• If the point is inside the background mesh and outside the
} STL it is an external mesh.
tolerance 2.0;
// Feature snapping
layers Note 1
{
wolf_wall Note 2
{
nSurfaceLayers 3;
//Local parameters
//expansionRatio 1.3;
//finalLayerThickness 0.3;
//minThickness 0.1;
}
}
// Advanced settings
nGrow 0;
featureAngle 130; Note 3 Note 1:
maxFaceThicknessRatio 0.5; In this section we select the patches where we want to add the
nSmoothSurfaceNormals 1; layers. We can add multiple patches (if they exist).
nSmoothThickness 10;
minMedianAxisAngle 90; Note 2:
maxThicknessToMedialRatio 0.3; This patch was created in the geometry section.
nSmoothNormals 3;
slipFeatureAngle 30; Note 3:
nRelaxIter 5; Specification of feature angle above which layers are collapsed
nBufferCellsNoExtrude 0; automatically.
nLayerIter 50;
nRelaxedIter 20; • In this step, we are generating the boundary layer mesh.
} 381
Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.
Mesh quality controls section
meshQualityControls
{
maxNonOrtho 75; Note 1
maxBoundarySkewness 20;
maxInternalSkewness 4; Note 2
maxConcave 80;
minVol 1E-13;
//minTetQuality 1e-15;
minTetQuality -1e+30;
minArea -1;
minTwist 0.02;
minDeterminant 0.001;
Note 1:
Maximum non-orthogonality angle.
minFaceWeight 0.05;
Note 2:
minVolRatio 0.01;
Maximum skewness angle.
minTriangleTwist -1;
• During the mesh generation process, the mesh quality is continuously
monitored.
minFlatness 0.5; • The mesher snappyHexMesh will try to generate a mesh using the
mesh quality parameters defined by the user.
nSmoothScale 4;
• If a mesh motion or topology change introduces a poor quality cell or
face the motion or topology change is undone to revert the mesh back
errorReduction 0.75;
to a previously valid error free state.
}
382
Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.
Mesh debug and write controls sections
debugFlags
(
// write intermediate meshes
mesh
writeFlags
(
// write volScalarField with cellLevel for • At the end of the dictionary you will find the sections: debugFlags
// postprocessing and writeFlags
scalarLevels
• By default they are commented. If you uncomment them you will
// write cellSets, faceSets of faces in layer enable debug information.
layerSets
• debugFlags and writeFlags will produce a lot of outputs that you
// write volScalarField for layer coverage can use to post process and troubleshoot the different steps of
layerFields the meshing process.
);
383
Mesh generation using snappyHexMesh
Let us generate the mesh of the wolf dynamics logo.
• This tutorial is located in the directory:
• $PTOFC/101SHM/M101_WD
• In this case we are going to generate a body fitted mesh with boundary layer. This is an
external mesh.
• Before generating the mesh take a look at the dictionaries and files that will be used.
• These are the dictionaries and files that will be used.
• system/snappyHexMeshDict
• system/surfaceFeaturesDict
• system/meshQualityDict
• system/blockMeshDict
• constant/triSurface/wolfExtruded.stl
• constant/triSurface/wolfExtruded.eMesh
• The file wolfExtruded.eMesh is generated after using the utility surfaceFeatures, which
reads the dictionary surfaceFeaturesDict.
384
Mesh generation using snappyHexMesh
Let us generate the mesh of the wolf dynamics logo.
1. $> foamCleanTutorials
2. $> blockMesh
3. $> surfaceFeatures
4. $> snappyHexMesh
5. $> checkMesh –latestTime
• In the case directory you will find the time folders 1, 2, and 3, which contain
the castellated mesh, snapped mesh and boundary layer mesh respectively.
In this case, snappyHexMesh automatically saved the intermediate steps.
• Before running the simulation, remember to transfer the solution from the
latest mesh to the directory constant/polyMesh, in the terminal type:
386
Mesh generation using snappyHexMesh
Let us generate the mesh of the wolf dynamics logo.
• If you want to avoid the additional steps of transferring the final mesh to the
directory constant/polyMesh by not saving the intermediate steps, you
can proceed as follows:
18 9 Name
19 ( Name and type of the surface patches
20 minX
21 { • The name and base type of the patch is given by the user.
22 type wall; Type
23 inGroups 1(wall);
24 nFaces 400; • In this case the name and base type was assigned in the
25
26 }
startFace 466399;
dictionaries blockMeshDict and snappyHexMeshDict.
27 maxX
28 {
nFaces • You can change the name if you do not like it. Do not use
29 type wall;
30 inGroups 1(wall); startFace strange symbols or white spaces.
31 nFaces 400;
32
33 }
startFace 466799;
• You can also change the base type. For instance, you can
34 minY change the type of the patch maxY from wall to patch.
35 {
36 type empty;
37 inGroups 1(wall);
38 nFaces 400;
39 startFace 467199; nFaces and startFace keywords
40 }
41 maxY • Unless you know what are you doing, you do not
42 {
43 type wall; need to change this information.
44 inGroups 1(wall);
45
46
nFaces
startFace
400;
467599;
• Basically, this is telling you the starting face and ending face
47 } of the patch.
48 minZ
49 {
50 type wall; • This information is created automatically when generating
51
52
inGroups
nFaces
1(wall);
400;
the mesh or converting the mesh.
53 startFace 467999;
54 }
390
Mesh generation using snappyHexMesh
The constant/polyMesh/boundary file
55 maxZ
56 { Name and type of the surface patches
57 type wall;
58 inGroups 1(wall); • The name and base type of the patch is given by the user.
59 nFaces 400;
60 startFace 466399;
61 } Name • In this case the name and base type was assigned in the
62
63
wolf_wall
{
dictionaries blockMeshDict and snappyHexMeshDict.
64 type wall; Type
65 inGroups 1(wall); • You can change the name if you do not like it. Do not use
66 nFaces 400;
67 startFace 466799; strange symbols or white spaces.
68 }
69
70
sphere
{ nFaces • You can also change the base type. For instance, you can
71 type empty; startFace change the type of the patch maxY from wall to patch.
72 inGroups 1(wall);
73 nFaces 400;
74 startFace 467199;
75 }
76 sphere_slave nFaces and startFace keywords
77 {
78 type wall; • Unless you know what are you doing, you do not
79 inGroups 1(wall);
80 nFaces 400; need to change this information.
81 startFace 467599;
82
83 )
}
• Basically, this is telling you the starting face and ending face
of the patch.
• This information is created automatically when generating
the mesh or converting the mesh.
391
Mesh generation using snappyHexMesh
• $> foamCleanTutorials
• $> foamCleanPolyMesh
• If you are planning to start the meshing from a previous saved state, you do
not need to clean the case directory.
392
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
393
snappyHexMesh guided tutorials
• Our first case will be a mesh around a cylinder.
• This is a simple geometry, but we will use it to study all the meshing steps
and introduce a few advanced features.
• This case is located in the directory $PTOFC/101SHM/M1cyl
394
snappyHexMesh guided tutorials
$PTOFC/101SHM/M1_cyl/C1
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
395
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
Sphere with no edge refinement Cylinder with edge refinement Cylinder with no edge refinement
• If the geometry has sharp angles and you want to resolve those edges, you should use edge
refinement.
• In the left figure there is no need to use edge refinement as there are no sharp angles.
• In the mid figure we used edge refinement to resolve the sharp angles.
• In the right figure we did not use edge refinement, therefore we did not resolve well the sharp
angles.
396
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• How do we control curvature refinement and enable edge refinement?
• In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls
{
...
...
...
...
...
...
...
...
...
} 397
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
resolveFeatureAngle
STL
398
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
angle
resolveFeatureAngle
STL
399
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• How do we control surface refinement?
• In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls
{
...
...
...
...
...
...
400
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• How do we create refinement regions?
• In the file snappyHexMeshDict, look for the following entry:
geometry
{
...
...
...
...
Dimensions of geometrical entity
...
...
};
401
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• How do we create refinement regions?
• In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls
{
...
...
...
refinementRegions
{ Name of the region
refinementBox created in the geometry section
{
mode inside; Type of refinement (inside,
levels ((1e15 1)); outside, or distance mode)
}
}
Refinement level
...
... Distance from the surface
... A large value covers the whole region
}
402
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
Explicit feature edge refinement level 0 Explicit feature edge refinement level 0
resolveFeatureAngle 110 resolveFeatureAngle 60
Surface based refinement level (2 2) Surface based refinement level (2 2)
Explicit feature edge refinement level 0 Explicit feature edge refinement level 4
resolveFeatureAngle 60 resolveFeatureAngle 60
Surface based refinement level (2 2) Surface based refinement level (2 2)
• To control edges refinement level, you can change the value of the explicit feature
edge refinement level.
404
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
Explicit feature edge refinement level 6 Explicit feature edge refinement level 0
resolveFeatureAngle 5 resolveFeatureAngle 5
Surface based refinement level (2 4) Surface based refinement level (2 4)
• To control edges refinement level, you can change the value of the explicit feature
edge refinement level.
405
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
Explicit feature edge refinement level 0 Explicit feature edge refinement level 4
resolveFeatureAngle 60 resolveFeatureAngle 60
Surface based refinement level (2 4) Surface based refinement level (2 2)
• To control surface refinement level, you can change the value of the surface based
refinement level.
• The first digit controls the global surface refinement level and the second digit
controls the curvature refinement level. 406
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
Explicit feature edge refinement level 0 Explicit feature edge refinement level 0
resolveFeatureAngle 60 resolveFeatureAngle 5
Surface based refinement level (2 4) Surface based refinement level (2 4)
• To control surface refinement due to curvature together with control based surface
refinement level, you can change the value of resolveFeatureAngle, and surface
based refinement level
407
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• Let us explore the dictionary surfaceFeaturesDict used by the utility
surfaceFeatures.
• This utility will extract surface features (sharp angles) according to an angle
criterion (includedAngle).
Features edges
Angle criterion
includedAngle 150;
to extract features
subsetFeatures
{ Keep non-manifold edges
nonManifoldEdges yes; (edges with more that 2
connected faces)
408
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• Let us explore the dictionary surfaceFeaturesDict used by the utility
surfaceFeatures.
• This utility will extract surface features (sharp angles) according to an angle
criterion (includedAngle).
angle
Angle criterion
includedAngle 150;
to extract features
subsetFeatures STL
{ Keep non-manifold edges includedAngle
nonManifoldEdges yes; (edges with more that 2
connected faces)
409
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• If you want to have a visual representation of the feature edges, you can use
paraview/paraFoam.
• Just look for the filter Feature Edges.
• Have in mind that the angle you need to define in paraview/paraFoam is the complement of the
angle you define in the dictionary surfaceFeaturesDict
410
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
• In this case we are going to generate a body fitted mesh with edge refinement. This is an
external mesh.
• These are the dictionaries and files that will be used.
• system/snappyHexMeshDict
• system/surfaceFeaturesDict
• system/meshQualityDict
• system/blockMeshDict
• constant/triSurface/surfacemesh.stl
• constant/triSurface/surfacemesh.eMesh
• The file surfacemesh.eMesh is generated after using the utility surfaceFeatures, which
reads the dictionary surfaceFeaturesDict.
• The utility surfaceFeatures, will save a set of *.obj files with the captured edges. These files
are located in the directory constant/extendedFeatureEdgeMesh. You can use paraview
to visualize the *.obj files.
411
snappyHexMesh guided tutorials
3D Cylinder with edge refinement.
1. $> foamCleanTutorials
2. $> surfaceFeatures
3. $> blockMesh
4. $> snappyHexMesh –overwrite
5. $> checkMesh –latestTime
6. $> paraFoam
$PTOFC/101SHM/M1_cyl/C2
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
413
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
414
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• How do we enable boundary layer?
• In the file snappyHexMeshDict, look for the following entry:
...
...
...
415
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• How do we enable boundary layer?
• In the file snappyHexMeshDict, look for the section addLayersControls:
addLayersControls
{
//Global parameters
relativeSizes true;
expansionRatio 1.2;
finalLayerThickness 0.5;
minThickness 0.1;
layers
{ Name of the surface or user-defined
banana_stlSurface patch where you want to add the
{ boundary layer mesh.
nSurfaceLayers 3;
}
}
// Advanced settings
...
...
...
416
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• How do we control boundary layer collapsing?
• In the file snappyHexMeshDict, look for the section addLayersControls:
addLayersControls
{
...
...
...
// Advanced settings
nGrow 0;
Increase this value to avoid BL
featureAngle 130; collapsing
...
...
...
417
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
418
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• When the option relativeSizes is true, the boundary layer meshing is done relative to the size
of the cells next to the surface.
• This option requires less user intervention but can not guarantee a uniform boundary layer.
• Also, it is quite difficult to set a desired thickness of the first layer.
419
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• When the option relativeSizes is false, we give the actual thickness of the layers.
• This option requires a lot user intervention but it guarantees a uniform boundary layer and the
desired layer thickness. 420
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• When the option relativeSizes is true and in order to have a uniform boundary layer, we need
to have a uniform surface refinement.
• Nevertheless, we still do not have control on the desired thickness of the first layer. 421
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• To avoid boundary layer collapsing close to the corners, we can increase the value of the
boundary layer parameter featureAngle. 422
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• The disadvantage of setting relativeSizes to false, is that it is difficult to control the expansion
ratio from the boundary layer meshing to the far mesh.
• To control this transition, we can add a refinement region at the surface with distance mode.
423
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
1. $> foamCleanTutorials
2. $> surfaceFeatures
3. $> blockMesh
4. $> snappyHexMesh -overwrite
5. $> checkMesh –latestTime
6. $> paraFoam
424
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• At the end of the meshing process you will get the following information
regarding the boundary layer meshing:
[m] [%]
• If you want to visualize the boundary layer thickness, you can enable
writeFlags in the snappyhexMeshDict dictionary,
...
...
...
writeFlags
(
scalarLevels; // write volScalarField with cellLevel for postprocessing
layerSets; // write cellSets, faceSets of faces in layer
layerFields; // write volScalarField for layer coverage
);
...
...
...
426
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• After creating the mesh and if you do not like the inflation layer or you want to
try different layer parameters, you do not need to start the meshing process
from scratch.
• To restart the meshing process from a saved state you need to save the
intermediate steps (castellation and snapping), and then create the inflation
layers starting from the snapped mesh.
• That is, do not use the option snappyHexMesh -overwrite.
• Also, in the dictionary controlDict remember to set the entry startFrom
to latestTime or the time directory where the snapped mesh is saved (in
this case 2).
• Before restarting the meshing, you will need to turn off the castellation and
snapping options and turn on the boundary layer options in the
snappyHexMeshDict dictionary.
428
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer.
• Remember, before restarting the meshing you will need to modify the
snappyHexMeshDict dictionary as follows:
castellatedMesh false;
snap false;
addLayers true;
• At this point, you can restart the meshing process by typing in the terminal,
• $> snappyHexMesh
• By the way, you can restart the boundary layer mesh from a previous mesh
with a boundary layer.
• So in theory, you an add one layer at a time, this will give you more control
but it will require more manual work and some scripting.
429
snappyHexMesh guided tutorials
• Meshing with snappyHexMesh – Case 3.
• 3D cylinder with feature edge refinement and boundary layer using a STL
with multiple surfaces (external mesh).
• You will find this case in the directory:
$PTOFC/101SHM/M1_cyl/C3
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
430
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
STL visualization with a single surface using paraview (the STL visualization with multiple surfaces using paraview (each
single surface in represented with a single color) color corresponds to a different surface)
• When you use a STL with multiple surfaces, you have more control over the meshing process.
• By default, STL files are made up of one single surface.
• If you want to create the multiple surfaces you will need to do it in the solid modeler.
• Alternatively, you can split the STL manually or using the utility surfaceAutoPatch.
• Loading multiple STLs is equivalent to using a STL with multiple surfaces.
431
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• When you use a STL with multiple surfaces, you have more control over the meshing process.
• In this case, we were able to use different refinement parameters in the lateral and central
surface patches of the cylinder. 432
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• How do we assign different names to different surface patches?
• In the file snappyHexMeshDict, look for the following entry:
geometry
{
surfacemesh.stl
{
type triSurfaceMesh;
name stlSurface;
regions
{
patch0 Named region in the STL file
{
name surface0; User-defined patch name
} This is the name you need to use when setting the
patch1 boundary layer meshing
{
name surface1;
}
patch2
{
name surface2;
}
}
}
...
...
...
}
433
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• How do we refine user defined surface patches?
• In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls
{
...
...
...
refinementSurfaces
{
level (2 2); Global refinement level
regions
{
patch0 Local surface patch
{
level (2 2); Local refinement level
patchInfo
{
type wall; Type of the patch.
} This information is optional
}
...
...
...
}
}
...
...
...
}
434
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• How do we control curvature refinement on surface patches?
• In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls
{
...
...
...
refinementSurfaces
{
level (2 2); Global refinement level
regions
{
patch0 Local surface patch
{
level (2 4); Local curvature refinement (in red)
patchInfo
{
type wall;
}
}
...
...
...
}
}
...
...
...
}
435
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• How do we control curvature refinement on surface patches?
• In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls
{
...
...
...
...
...
...
436
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• How do we control boundary layer meshing on the surface patches?
• In the file snappyHexMeshDict, look for the following entry:
addLayersControls
{
//Global parameters
relativeSizes true;
expansionRatio 1.2;
Global BL parameters
finalLayerThickness 0.5;
minThickness 0.1;
layers
{
“surface.*” POSIX wildcards are permitted
{
nSurfaceLayers 5;
}
surface0 Local surface patch
{
nSurfaceLayers 3;
expansionRatio 1.0;
finalLayerThickness 0.25; Local BL parameters
minThickness 0.1;
}
}
//Advanced settings
...
...
...
} 437
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
1. $> cd geo
4. $> cd ..
5. $> paraview
• The utility surfaceAutoPatch will read the original STL file (geo.stl), and it will find the
patches using an angle criterion of 130 (similar to the angle criterion used with the utility
surfaceFeatures). It writes the new STL geometry in the file output.stl.
• By the way, it is better to create the STL file with multiple surfaces directly in the solid modeler.
• FYI, there is an equivalent utility for meshes, autoPatch. So if you forgot to define the
patches, this utility will automatically find the patches according to an angle criterion. 438
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• If you open the file output.stl, you will notice that there are three
surfaces defined in the STL file. The different surfaces are defined in by the
following sections:
solid patch0
… Surface patch 1 • The name of the solid sections are
automatically given by the utility
endsolid patch0
surfaceAutoPatch.
solid patch1
• The convention is as follows: patch0,
… Surface patch 2
patch1, patch2, … patchN.
endsolid patch1
endsolid patch2
439
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
1. $> foamCleanTutorials
2. $> surfaceFeatures
3. $> blockMesh
4. $> snappyHexMesh -overwrite
5. $> checkMesh –latestTime
440
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
• This case is ready to run using the solver simpleFoam. But before running,
you will need to set the boundary and initial conditions.
• You will need to manually modify the file constant/polyMesh/boundary
• Remember:
• Base type boundary conditions are defined in the file boundary located
in the directory constant/polyMesh.
• Numerical type boundary conditions are defined in the field variables
files located in the directory 0 or the time directory from which you want
to start the simulation (e.g. U, p).
• The name of the base type boundary conditions and numerical type
boundary conditions needs to be the same.
• Also, the base type boundary condition needs to be compatible with the
numerical type boundary condition.
441
snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces.
1. $> sh run_all.sh
442
snappyHexMesh guided tutorials
$PTOFC/101SHM/M1_cyl/C4
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
443
snappyHexMesh guided tutorials
2D Cylinder
From 3D To 2D
• To generate a 2D mesh using snappyHexMesh, we need to start from a 3D. After all,
snappyHexMesh is a 3D mesher.
• To generate a 2D mesh (and after generating the 3D mesh), we use the utility
extrudeMesh.
• The utility extrudeMesh works by projecting a face into a mirror face. Therefore,
the faces need to parallel. 444
snappyHexMesh guided tutorials
2D Cylinder
Geometry width
FACE 1
• At most, the input geometry and the background mesh need to have the same width.
• If the input geometry is larger than the background mesh, it will be automatically cut by the faces
of the background mesh.
• In this case, the input geometry will be cut by the two lateral patches of the background mesh.
• If you want to take advantage of symmetry in 3D, you can cut the geometry in half using one of
the faces of the background mesh.
• When dealing with 2D
• Extracting the features edges is optional for the 2D geometry extremes, but it is recommended if
there are internal edges that you want to resolve.
445
snappyHexMesh guided tutorials
2D Cylinder
• How do we create the 2D mesh?
• After generating the 3D mesh, we use the utility extrudeMesh.
• This utility reads the extrudeMeshDict,
constructFrom patch;
sourceCase “.”
sourcePatches (minZ); Name of source patch
extrudeModel linearNormal
Number of layers to use in the linear extrusion.
nLayers 1;
As this is a 2D case we must use 1 layer
linearNormalCoeffs
{
Thickness of the extrusion.
thickness 1;
It is highly recommended to use a value of 1
}
mergeFaces false;
446
snappyHexMesh guided tutorials
2D Cylinder
1. $> foamCleanTutorials
2. $> blockMesh
3. $> snappyHexMesh –overwrite
4. $> extrudeMesh
5. $> checkMesh –latestTime
6. $> paraFoam
448
snappyHexMesh guided tutorials
$PTOFC/101SHM/M2_mixing_elbow
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
449
snappyHexMesh guided tutorials
Mixing elbow.
castellatedMeshControls
{
...
...
...
refinementRegions
{
mixing_elbow Name of surface
{
mode distance; Refinement using distance mode
levels ((1e-4 1));
}
}
452
snappyHexMesh guided tutorials
Mixing elbow.
• At this point, we are going to work in parallel (but you can work in serial as
well).
• To generate the mesh, in the terminal window type:
1. $> foamCleanTutorials
2. $> surfaceFeatures
3. $> blockMesh
4. $> decomposePar
5. $> mpirun -np 4 snappyHexMesh –parallel –overwrite
6. $> mpirun -np 4 checkMesh –parallel –latestTime
7. $> reconstructParMesh -constant
8. $> paraFoam
453
snappyHexMesh guided tutorials
Mixing elbow.
• So what did we do?
• Step 4: we distribute the mesh among the processors we want to use.
• Step 5 and 6: we run in parallel.
• Step 7: we put back together the decomposed mesh.
• Step 8: we visualize the reconstructed mesh.
455
snappyHexMesh guided tutorials
Mixing elbow.
• Empty patches are no problem, they remain from the background mesh.
• To erase the empty patches, you can do it manually (you will need to modify the file
boundary), or you can use the utility createPatch as follows (the utility runs in
parallel):
• $> createPatch -overwrite
• The surface patch pipe was created in the geometry section of the dictionary
snappyHexMeshDict.
• The patches mixing_elbow_outlet, mixing_elbow_inlet1 and
mixing_elbow_inlet2 were created automatically by snappyHexMesh.
• You have the choice of giving the names of the patches yourself or letting
snappyHexMesh assign the names automatically.
• Remember, when creating the boundary layer mesh, these are the names you need
to use to assign the layers.
456
snappyHexMesh guided tutorials
Mixing elbow.
• The mesh used in the previous case was a STL with multiple surfaces.
• In you do not create the regions in the geometry section of the dictionary
snappyHexMeshDict, snappyHexMesh will automatically assign the names of the
surface patches as follows:
system/surfaceFeaturesDict
…
• mixing_elbow_outlet …
• mixing_elbow_inlet1 geometry
{
surfacemesh.stl
• mixing_elbow_inlet2 {
type triSurfaceMesh;
name mixing_elbow;
regions
{
pipe NOTE 1
{
NOTE 2 name pipe;
}
}
}
NOTE 1:
};
This is the name of the region or surface patch in the STL file
…
NOTE 2:
…
User-defined patch name. This is the final name of the patch.
457
snappyHexMesh guided tutorials
Mixing elbow.
• The mesh used in the previous case was a STL with multiple surfaces.
• In you do not create the regions in the geometry section of the dictionary
snappyHexMeshDict, snappyHexMesh will automatically assign the names of the
surface patches as follows:
constant/triSurface/surfacemesh.stl
• mixing_elbow_outlet
solid outlet
• mixing_elbow_inlet1 …
…
…
• mixing_elbow_inlet2 solid outlet
solid inlet1
…
…
…
solid inlet1
solid inlet2
…
…
…
solid inlet2
458
snappyHexMesh guided tutorials
Mixing elbow.
• The mesh used in the previous case was a STL with multiple surfaces.
• In the directory geometry, you fill find the file allss.stl, this STL has one
single surface.
• Try to use this STL file to generate the mesh.
• You will notice that the final mesh has only one patch, namely
mixing_elbow (or whatever name you chose).
• Also, it is not possible to have local control on the mesh refinement and
boundary layer meshing.
• You will also face the conundrum that as there is only one surface patch, it is
not possible to assign boundary conditions.
459
snappyHexMesh guided tutorials
Mixing elbow.
• To solve the problem of the single surface patch, you can use the utility autoPatch.
To do so, you can proceed as follows:
• $> autoPatch 60 -overwrite
• The option -overwrite, will copy the new mesh in the directory
constant/polyMesh.
• The utility autoPatch will use an angle criterion to find the patches, and will assign
the name auto0, auto1, auto2 and auto3 to the new patches.
• The angle criterion is similar to that of the utility surfaceFeatures.
• The only difference is that it uses the complement of the angle. So, the smaller the
angle the more patches it will find.
• The naming convention is autoN, where N is the patch number.
• Remember, autoPatch will manipulate the mesh located in the directory
constant/polyMesh.
• FYI, autoPatch does not un in parallel.
460
snappyHexMesh guided tutorials
Exercises
• To get a feeling of the includedAngle value, try to change the value in the dictionary
surfaceFeaturesDict.
• Remember the higher the includedAngle value, the more features you will capture.
• In the dictionary snappyHexMeshDict, change the value of resolveFeatureAngle (try to use a lower value),
and check the mesh quality in the intersection between both pipes.
• In the castellatedMeshControls section, try to disable or modify the distance refinement of the
mixing_elbow region (refinementRegions).
• What difference do you see in the output?
• Starting from the body fitted mesh, add 3 inflation layers at the walls (save the intermediate step).
• Try to add local surface refinement at the surface patch inlet2 (look at the STL file
constant/triSurface/surfacemesh_multi.stl).
• Using paraview, extract the feature edge at the joint section of the pipes. Then, try to add local refinement at
this feature edge.
• Try to add curvature refinement at the feature edge extracted from the surface patch inlet1.
461
snappyHexMesh guided tutorials
Exercises
• Use the STL file with a single surface (surfacemesh_single.stl) and generate the same mesh, do not
add inflation layers.
• Use the utility autopatch to split the mesh in different surface patches. To get a feeling on how to use
this utility, use different angle values. Try to get four surface patches.
• After splitting the mesh in four surface patches, rename the boundary patches using the utility
createPatch.
• After renaming the boundary patches, change the type of each one using the utility foamDictionary.
• Starting from the body fitted mesh, add 3 inflation layers at the walls (do not save the intermediate step).
• Hints: if you do not know how to use the utilities createPatch and foamDictionary, look at the
script file run_mesh_single_surface.sh
• After generating the mesh, setup a simple incompressible simulation (with no turbulence model).
• Set the inlet velocity to 1 at both inlet patches and use a dynamic viscosity value equal to 0.01. Run the
simulation in steady and unsteady mode.
462
snappyHexMesh guided tutorials
$PTOFC/101SHM/M4_ahmed
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
463
snappyHexMesh guided tutorials
Ahmed body
465
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
466
Mesh conversion
• OpenFOAM® gives users a lot of flexibility when it comes to meshing.
• You are not constrained to use OpenFOAM® meshing tools.
• To convert a mesh generated with a third-party software to OpenFOAM® format, you can use
the OpenFOAM® mesh conversion utilities.
• If your format is not supported, you can write your own conversion tool.
• By the way, many of the commercially available meshers can save the mesh in OpenFOAM®
format or in a compatible format.
• In the directory $PTOFC/mesh_conversion_sandbox you will find a few meshes generated
using the most popular third-party mesh generation applications.
• Feel free to play with these meshes.
• In the README.FIRST file of each case, you will find the instructions of how to convert the
mesh.
• Remember to always check the file boundary after converting the mesh. You
will need to change the name and type of the surface patches according to what
you would intent to do.
• Also, to convert the mesh you need to be in the top level of the case directory,
and you need to give to the conversion utility the path (absolute or relative) of
the mesh to be converted.
467
Mesh conversion
• In the directory $FOAM_UTILITIES/mesh/conversion you will find the source
code for the mesh conversion utilities:
• ansysToFoam • kivaToFoam
• cfx4ToFoam • mshToFoam
• datToFoam • netgenNeutralToFoam
• fluent3DMeshToFoam • Optional/ccm26ToFoam
• fluentMeshToFoam • plot3dToFoam
• foamMeshToFluent • sammToFoam
• foamToStarMesh • star3ToFoam
• foamToSurface • star4ToFoam
• gambitToFoam • tetgenToFoam
• gmshToFoam • vtkUnstructuredToFoam
• ideasUnvToFoam • writeMeshObj
• Take your time and read the instructions/comments contained in the source code of
the mesh conversion utilities so you can understand how to use these powerful tools.
468
Mesh conversion
$PTOFC/mesh_conversion_sandbox/M1_mixing_elbow_salome
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
469
Mesh conversion
Case 1. Mixing elbow (internal mesh).
1. $> foamCleanTutorials
2. $> foamCleanPolyMesh
3. $> ideasUnvToFoam ../../meshes_and_geometries/salome_elbow3d/Mesh_1.unv
4. $> checkMesh
5. $> paraFoam
• Remember to always check the file boundary after converting the mesh.
• To convert the mesh, you need to be in the top level of the case directory, and you
need to give the path (absolute or relative) of the mesh to be converted.
470
Mesh conversion
Case 1. Mixing elbow (internal mesh).
• ideasUnvToFoam output.
Create time
Processing tag:2411
Starting reading points at line 3.
Read 31136 points.
Processing tag:2412
Starting reading cells at line 62278.
First occurrence of element type 11 for cell 1 at line 62279
First occurrence of element type 41 for cell 361 at line 63359
First occurrence of element type 111 for cell 20933 at line 104503
Read 151064 cells and 20572 boundary faces. Internal cells and boundary faces read
Processing tag:2467
Starting reading patches at line 406633.
For group 1 named pipe trying to read 19778 patch face indices.
For group 2 named inlet1 trying to read 358 patch face indices.
For group 3 named inlet2 trying to read 78 patch face indices.
For group 4 named outlet trying to read 358 patch face indices.
End
471
Mesh conversion
Case 1. Mixing elbow (internal mesh).
• checkMesh output.
Mesh stats
points: 31136
faces: 312414
internal faces: 291842
cells: 151064
faces per cell: 4
boundary patches: 4
point zones: 0
face zones: 0
cell zones: 0
Checking topology...
Boundary definition OK.
Cell to face addressing OK.
Point usage OK.
Upper triangular ordering OK.
Face vertices OK.
Number of regions: 1 (OK).
472
Mesh conversion
Case 1. Mixing elbow (internal mesh).
• checkMesh output.
Checking geometry...
Overall domain bounding box (0 -0.414214 -0.5) (5 5 0.5)
Mesh has 3 geometric (non-empty/wedge) directions (1 1 1)
Mesh has 3 solution (non-empty) directions (1 1 1)
Boundary openness (-1.0302e-17 -6.17232e-17 -1.77089e-16) OK.
Max cell openness = 2.32045e-16 OK.
Max aspect ratio = 4.67245 OK.
Minimum face area = 0.000286852. Maximum face area = 0.010949. Face area magnitudes OK.
Min volume = 2.74496e-06. Max volume = 0.00035228. Total volume = 6.75221. Cell volumes OK.
Mesh non-orthogonality Max: 54.2178 average: 15.1295
Non-orthogonality check OK.
Face pyramids OK.
Max skewness = 0.649359 OK.
Coupled point location match (average 0) OK.
End
473
Mesh conversion
Case 1. Mixing elbow (internal mesh).
• The boundary file.
474
Mesh conversion
Case 1. Mixing elbow (internal mesh).
• The boundary file.
4
(
pipe
{
type
nFaces
patch;
19778;
Base type of the boundary patches
startFace 291842;
}
inlet1
{
• In this case, the utility automatically
type patch; assigned the base type patch to all
nFaces 358;
startFace 311620; boundary patches.
}
inlet2
{
• Feel free to change the base type
type
nFaces
patch;
78;
according to your needs.
startFace 311978;
} • In this case, it will be wise to change
outlet
{
the base type of patch pipe to wall.
type patch;
nFaces 358;
startFace 312056;
}
)
475
Mesh conversion
Exercises
• Remember, you can change the name and type of the boundary patches manually, but as we want to do
things automatically, we will use the utilities createPatch and foamDictionary
• After converting the mesh to OpenFOAM® format, rename the boundary patches using the utility
createPatch.
• After converting the mesh to OpenFOAM® format, change the type of each boundary patch using the
utility foamDictionary.
• After converting the mesh to OpenFOAM® format, add 5 inflation layers at the walls (do not save the
intermediate step).
• Check the mesh quality before and after adding the inflation layers.
• After generating the mesh, setup a simple incompressible simulation (with no turbulence model).
• Set the inlet velocity to 1 at both inlet patches and use a dynamic viscosity value equal to 0.01. Run the
simulation in steady and unsteady mode.
476
Roadmap
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
4. Mesh generation using blockMesh.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
477
Geometry and mesh manipulation utilities
• First of all, by mesh manipulation we mean modifying a valid OpenFOAM®
mesh.
• These modifications can be scaling, rotation, translation, mirroring,
topological changes, mesh refinement and so on.
• In the directory $FOAM_UTILITIES/mesh/manipulation you will find the
mesh manipulation utilities. Just to name a few:
• autoPatch • rotateMesh
• checkMesh • setSet
• createBaffles • splitMesh
• mergeMeshes • splitMeshRegions
• mergerOrSplitBaffles • stitchMesh
• mirrorMesh • subsetMesh
• polyDualMesh • topoSet
• refineMesh • transformPoints
• renumberMesh
478
Geometry and mesh manipulation utilities
• In the directory $FOAM_UTILITIES/mesh/manipulation you will find the
following mesh manipulation utilities.
• Inside each utility directory you will find a *.C file with the same name as the
directory. This is the main file, where you will find the top-level source code and a
short description of the utility.
• For instance, in the directory checkMesh, you will find the file checkMesh.C, which
is the source code of the utility checkMesh. In the source code you will find the
following description:
Usage
- checkMesh [OPTION]
\param -allGeometry \n
Checks all (including non finite-volume specific) geometry
\param -allTopology \n
Checks all (including non finite-volume specific) addressing
\param -meshQuality \n
Checks against user defined (in \a system/meshQualityDict) quality settings
• surfaceAdd • surfaceMeshConvert
• surfaceAutoPatch • surfaceMeshExport
• surfaceBooleanFeatures • surfaceMeshTriangulate
• surfaceCheck • surfaceOrient
• surfaceConvert • surfaceSplitByPatch
• surfaceFeatureConvert • surfaceSubset
• surfaceFeatures • surfaceToPatch
• surfaceInertia • surfaceTransformPoints
480
Geometry and mesh manipulation utilities
• In the directory $FOAM_UTILITIES/surface you will find the following surface
manipulation utilities.
• Inside each utility directory you will find a *.C file with the same name as the
directory. This is the main file, where you will find the top-level source code and a
short description of the utility.
• For instance, in the directory surfaceTransformPoints, you will find the file
surfaceTransformPoints.C, which is the source code of the utility
surfaceTransformPoints. In the source code you will find the following
description:
481
Geometry and mesh manipulation utilities
$PTOFC/mesh_quality_manipulation/M5_ahmed_body_transform
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
482
Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM®
• We will now manipulate a STL geometry. In the terminal type:
1. $> foamCleanTutorials
2. $> surfaceMeshInfo ./constant/triSurface/ahmed_body.stl
3. $> surfaceCheck ./constant/triSurface/ahmed_body.stl
$> surfaceTransformPoints -rollPitchYaw '(0 0 15)’
4. ./constant/triSurface/ahmed_body.stl rotated.stl
$> surfaceTransformPoints -translate '(0 0.12 0)'
5. ./constant/triSurface/ahmed_body.stl translated.stl
$> surfaceTransformPoints -scale '(0.9 1.1 1.3)'
6. ./constant/triSurface/ahmed_body.stl scaled.stl
$> surfaceInertia -density 2700 –noFunctionObjects
7. ./constant/triSurface/ahmed_body.stl
$> surfaceOrient ./constant/triSurface/ahmed_body_wrong_normals.stl
8. out.stl ‘(1e10 1e10 1e10)’
483
Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM®
• In step 2 we use the utility surfaceMeshInfo to get general information about the STL (such
as number of faces and so on).
• In step 3 we use the utility surfaceCheck to check the STL file.
• In step 4 we use the utility surfaceTransformPoints to rotate the STL. We read in the STL
./constant/triSurface/ahmed_body.stl and we write out the STL rotated.stl
• In step 5 we use the utility surfaceTransformPoints to translate the STL. We read in the
STL ./constant/triSurface/ahmed_body.stl and we write out the STL
translated.stl
• In step 6 we use the utility surfaceTransformPoints to scale the STL. We read in the STL
./constant/triSurface/ahmed_body.stl and we write out the STL scaled.stl
• In step 7 we use the utility surfaceInertia to compute the inertia of the STL. We read in the
STL ./constant/triSurface/ahmed_body.stl. Notice that we need to give a reference
density value.
• In step 8 we use the utility surfaceOrient to orient the normals of the STL in the same way.
We read in the STL ./constant/triSurface/ahmed_body_wrong_normals.stl and we
write out the STL out.stl. Notice that we give an outside point or ‘(1e10 1e10 1e10)’, if
this point is outside the STL all normals will be oriented outwards, if the point is inside the STL
all normals will be oriented inwards.
484
Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM®
• Pay particular attention to step 8.
• We already have seen that snappyHexMesh computes surface angles using the surface
normals as a reference, so it is extremely important to have the normals oriented in the same
way and preferably outwards.
485
Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM®
• To plot the normals in paraview/paraFoam you can use the filter Normal Glyphs
Select the Normal Glyphs from the filter menu
486
Geometry and mesh manipulation utilities
$PTOFC/mesh_quality_manipulation/M7_cylinder_transform
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
487
Geometry and mesh manipulation utilities
Mesh manipulation in OpenFOAM®
• We will now manipulate a mesh. In the terminal type:
1. $> foamCleanTutorials
2. $> blockMesh
3. $> transformPoints -rollPitchYaw '(0 0 90)'
4. $> transformPoints -scale '(0.01 0.01 0.01)'
5. $> transformPoints -translate '(0 0 1)'
6. $> createPatch -noFunctionObjects –overwrite
7. $> checkMesh
8. $> paraFoam
• In step 3 we use the utility transformPoints to rotate the mesh. We rotate the mesh by 90° about the Z
axis.
• In step 4 we use the utility transformPoints to scale the mesh. We scale the mesh by a factor of '(0.01
0.01 0.01)'.
• In step 5 we use the utility transformPoints to translate the mesh. We translate the mesh by the vector
'(0 0 1)'.
• In step 6 we use the utility createPatch to rename the patches of the mesh. This utility reads the dictionary
system/createPatchDict. Instead of using the utility createPatch we could have modified the
boundary file directly.
• This case is ready to run using the solver buoyantBoussinesqPimpleFoam. 488
Geometry and mesh manipulation utilities
Mesh manipulation in OpenFOAM®
Original mesh
490
Roadmap
1. Running in parallel
491
Running in parallel
• First of all, to know how many processors/cores you have available in your computer, type in the
terminal:
• $> lscpu
• The output for this particular workstation is the following:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Total number of cores available after
CPU(s): 24
hyper threading (virtual cores)
On-line CPU(s) list: 0-23
Thread(s) per core: 2
Core(s) per socket: 6 Number of threads per core (hyper threading)
Socket(s): 2
NUMA node(s): 2
Vendor ID: GenuineIntel Number of cores per socket or physical
CPU family: 6 processor
Model: 44
Model name: Intel(R) Xeon(R) CPU X5670 @ 2.93GHz
Stepping: 2 Number of sockets (physical processors)
CPU MHz: 1600.000
CPU max MHz: 2934.0000
CPU min MHz: 1600.0000
BogoMIPS: 5851.91
Total number of physical cores
Virtualization: VT-x
=
L1d cache: 32K
Number of cores per socket X Number of sockets
L1i cache: 32K
L2 cache: 256K
L3 cache: 12288K Total number of physical cores = 6 X 2 = 12 cores
NUMA node0 CPU(s): 0-5,12-17
NUMA node1 CPU(s): 6-11,18-23
• To take full advantage of the hardware, we use the maximum number of physical
cores (12 physical cores in this case) when running in parallel.
• If you use the maximum number of virtual cores, OpenFOAM® will run but it will be
slower in comparison to running with the maximum number of physical cores (or even
less cores).
• Same rule applies when running in clusters/super computers, so always read the
hardware specifications to know the limitations.
493
Running in parallel
Why use parallel computing?
Thanks to parallel computing we can solve bigger problems (scalability). A single computer has limited
physical memory, many computers interconnected have access to more memory (distributed memory).
A single computer or processor can only do one thing at a time. Multiple processors or computing
resources can do many things simultaneously.
Run faster (speed-up) and increase your productivity, with the potential of saving money in the design
process.
• Save money:
In theory, throwing more resources at a task will shorten its time to completion, with potential cost
savings. Parallel computers can be built from cheap, commodity components.
Both physical and practical reasons pose significant constraints to simply building ever faster serial
computers (e.g, transmission speed, CPU clock rate, limits to miniaturization, hardware cooling).
494
Running in parallel
Speed-up and scalability example
• In the context of high-performance computing (HPC), there are two common metrics that measure the
scalability of the application:
• Strong scaling (Amdahl’s law): which is defined as how the solution time varies with the number of
processors for a fixed problem size (number of cells in CFD)
• Weak scaling (Gustafson’s law): which is defined as how the solution time varies with the number of
processors for a fixed problem size per processor (or increasing the problem size with a fix number of
processors).
• In this example, when we reach 12 cores inter-processor communication slow-downs the computation. But if we
increase the problem size for a fix number of processors, we will increase the speed-up.
• The parallel case with 1 processor runs slower than the serial case due to the extra overhead when calling the
MPI library. 495
Running in parallel
• The method of parallel computing used by OpenFOAM® is known as domain
decomposition, in which the geometry and associated fields are broken into pieces
and distributed among different processors.
497
Running in parallel
To run OpenFOAM® in parallel you will need to:
• In this example, we are subdividing the domain in 128 subdomains, therefore we should have
128 physical cores available.
• The main goal of domain decomposition is to minimize the inter-processors communication and
the processor workload.
499
Running in parallel
Domain Decomposition Methods
• These are the decomposition methods available in OpenFOAM® 8. To name a few:
• hierarchical
• manual
• metis
• multiLevel
• none We highly recommend you to use this method.
The only input that requires from the user is
• scotch the number of subdomains/cores. This method
attempts to minimize the number of processor
• simple
boundaries.
• structured
• If you want more information about each decomposition method, just read the source code:
• $WM_PROJECT_DIR/src/parallel/decompose/
500
Running in parallel
Running in parallel – Gathering all together
decomposePar
• Inside each processorN directory you will have the mesh information, boundary conditions,
initial conditions, and the solution for that processor.
501
Running in parallel
Running in parallel – Gathering all together
• After decomposing the mesh, we can run in parallel using MPI.
• The number of processors to use or <NPROCS>, needs to be the same as the number of
partitions (numberOfSubdomains).
• Do not forget to use the flag –parallel.
502
Running in parallel
Running in parallel – Gathering all together
• In the decomposed case, you will find the mesh
information, boundary conditions, initial conditions, and
the solution for every processor.
• The information is inside the directory processorN
(where N is the processor number).
reconstructPar
• When you reconstruct the case, you glue together all the
information contained in the decomposed case.
• All the information (mesh, boundary conditions, initial
conditions, and the solution), is transfer to the original
case folder (polyMesh and time solution directories).
503
Running in parallel
Running in parallel – Gathering all together
• Summarizing, to run in parallel we proceed in the following way:
1. $> decomposePar
2. $> mpirun –np <NPROCS> <application/utility> –parallel
3. $> reconstructPar
• You can do the post-processing and visualization on the decomposed case or reconstructed
case. We are going to address this later on.
• If you are dealing with moving bodies where the mesh topology is changed or if you are using
AMR, you will need to use reconstructParMesh before reconstrucPar.
504
Running in parallel
Kelvin Helmholtz instability in a coarse mesh
Mesh size
Processors Clock time (seconds)
in x, y, and z directions
Volume fraction
www.wolfdynamics.com/wiki/kelvin_helmholtz/ani1.gif
• The traditional way is to first reconstruct the case and then do the post-processing and
visualization on the reconstructed case.
• To do so, we type in the terminal:
1. $> reconstructPar
2. $> paraFoam
• Step 1 reconstruct the case. Remember, you can choose to reconstruct all the time steps, the
last time step or a range of time steps.
• In step 2, we use paraFoam to visualize the reconstructed case.
506
Running in parallel
Visualization of a parallel case
• An alternative way to visualize the solution, is by proceeding in the following way
• $> paraFoam –builtin
507
Running in parallel
Visualization of a parallel case
• Both of the previous methods are valid.
• When we use the option –builtin with paraFoam, we have the option to work on the
decomposed case directly. In other words, we do not need to reconstruct the case.
• This option is also faster than running paraFoam with no flags.
• But wait, there is a third option.
• The third option consist in post-processing each decomposed domain individually.
• To load all processor directories, you will need to manually create the file
processorN.OpenFOAM (where N is the processor number) in each processor folder.
• After creating all processorN.OpenFOAM files, you can launch paraFoam and load each file
(the processorN.OpenFOAM files).
• As you can see, this option requires more input from the user.
508
Running in parallel
Decomposing big meshes
• One final word, the utility decomposePar does not run in parallel.
• So, it is not possible to distribute the mesh among different computing nodes to do the
partitioning in parallel.
• If you need to partition big meshes, you will need a computing node with enough memory to
handle the mesh.
• We have been able to decompose meshes with up to 500 000 000 elements, but we used a
computing node with 512 gigs of memory.
• For example, in a computing node with 16 gigs of memory, it is not possible to decompose a
mesh with 30 000 000. You will need to use a computing node with at least 32 gigs of memory.
• Same applies for the utility reconstructPar.
509
Running in parallel
Do all utilities run in parallel?
• At this point, you might be wondering if all solvers/utilities run in parallel.
• To know what solvers/utilities do not run in parallel, in the terminal type:
• $> find $WM_PROJECT_DIR -type f | xargs grep –sl ‘noParallel’
• Paradoxically, the utilities used to decompose the domain and reconstruct the domain do not
run in parallel.
• Another important utility that does not run in parallel is blockMesh. So to generate big meshes
with blockMesh you need to use a big fat computing node.
• Another important utility that does not run in parallel by default is paraFoam.
• To compile paraFoam with MPI support, in the file makeParaView (located in the directory
$WM_THIRD_PARTY_DIR), set the option withMPI to true,
• withMPI = true
• While you are working with the file makeParaView, you might consider enabling Python
support,
• withPYTHON = true
510
Running in parallel
Exercises
• Choose any tutorial or design your own case and do a scalability test. Scale your case with two different
meshes (a coarse and a fine mesh).
• Run the same case using different partitioning methods. Which method scales better? Do you get the same
results?
• Do you think that the best partitioning method is problem dependent?
• Compare the wall time of a test case using the maximum number of cores and the maximum number of virtual
cores. Which scenario is faster and why?
• Run a parallel case without using the –parallel option. Does it run? Is it faster of slower? How many
outputs do you see on the screen?
• Do you get any speed-up by using renumberMesh?
• What applications do not run in parallel?
511
Module 5
The postprocess utility – Sampling – Probing
– On-the-fly postprocessing – Field
manipulation – Data conversion
512
Roadmap
513
On-the-fly postprocessing – functionObjects
514
On-the-fly postprocessing – functionObjects
• In the directory $FOAM_SRC/functionObjects you will find the source code for the
functionObjects.
• There are many functionObjects, and according to what they do, they are located in different
sub-directories, namely, field, forces, lagrangian, solvers, and utilities. Just to
name a few functionObjects:
• courantNo • forceCoeffs
• div • forces
• fieldAverage • icoUncoupledKinematicCloud
• fieldMinMax • scalarTransport
• grad • codedFunctionObject
• MachNo • residuals
• Q • systemCall
• vorticity • timeActivatedFileUpdate
• yPlus • writeObjects
// ...
// functionObject Keywords and sub-dictionaries
// keywords and sub-dictionaries specific to the functionObject
// ...
516
On-the-fly postprocessing – functionObjects
• There are many functionObjects implemented in OpenFOAM®, and sometimes is
not very straightforward how to use a specific functionObject.
• Also, functionObjects can have many options and some limitations.
• Our best advice is to read the doxygen documentation or the source code to learn
how to use functionObjects.
• Remember, the source code of the functionObjects is located in the directory:
$WM_PROJECT_DIR/src/postProcessing/functionObjects
• The source code of the sampling and co-processing utilities is located in the directory:
$WM_PROJECT_DIR/src/sampling
• The source code of the database entries required for the functionObjects is located
in the directory:
$FOAM_SRC/OpenFOAM/db/functionObjects
$PTOFC/101postprocessing/MDA_30P30N
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
518
On-the-fly postprocessing – functionObjects
At the end of the day, you should get something like this
cd cl
• Let us run this case using the automatic scripts distributed with the tutorial. In the
terminal type:
1. $> sh run_all.sh
• After the simulation is finish, you will find the decomposed directories (processor0,
processor1, processor2 and processor3), the postProcessing directory,
and the 2000 directory. The solution, and output of the functionObjects, is saved in
these directories.
• Remember, to visualize the decomposed solution you will need to launch paraFoam
as follows,
• Do not erase the solution as we are going to use it in the next section.
522
On-the-fly postprocessing – functionObjects
The controlDict dictionary
• Let us take a look at the bottom of the controlDict
51 functions dictionary file. In this dictionary is where we define all
52 {
functionObjects.
name_of_the_functionObject_dictionary
{ • Within this dictionary, functionObjects are defined in
}
Sub-dictionary with functionObject entries
the sub-dictionary functions, i.e.,
70 //// Name of fields Name of the velocity and pressure fields. If you use
71 pName p;
72 Uname U; different fields, e.g., pMean and Umean, they need to be
computed before this functionObject
74 //only for incompressible flows Reference density value. It only needs to be defined for
75 rho rhoInf;
76 rhoInf 1.0;
incompressible flows. For compressible flows, the
computed density is used instead (you will need to define
a dummy value, though)
78 //// Centre of rotation
79 CofR (0 0 0); Reference center of rotation to compute moments
80 }
Note:
211 } • The source code of this functionObject is located in the directory
$FOAM_SRC/functionObjects/forces/forces
• Use the banana method to know all the options available for each entry. 525
On-the-fly postprocessing – functionObjects
The controlDict dictionary
• Let us study now the functionObject used to
51 functions
52 { functionObject compute the force coefficients.
86 forceCoeffs_object
identifier (user given)
87 {
88 type forceCoeffs;
89 functionObjectLibs ("libforces.so");
90
91 enabled true;
92 • This functionObject computes the force coefficients.
93 patches ("wall_slat" "wall_airfoil" "wall_flap");
94
• These entries are similar to those of the force
95 pName p; functionObject
96 Uname U;
97
99 rho rhoInf;
100 rhoInf 1.0;
101
This option will output the values to a text file located in the
103 log true; directory postProcessing/forceCoeffs_object
104
105 CofR (0.0 0 0);
106 Reference center of rotation to compute moments
107 pitchAxis (0 0 1);
108 magUInf 1.0;
109 lRef 1; Reference values used to compute coefficients
110 Aref 1;
111
115 writeControl timeStep;
116 writeInterval 1; Controls for saving frequency
117
119 liftDir (0 1 0);
120 dragDir (1 0 0); Reference axes to compute the lift and drag coefficients.
121
125 }
211 }
526
On-the-fly postprocessing – functionObjects
The controlDict dictionary
• Let us study now the functionObject used to
51 functions
52 { functionObject compute the force coefficients.
86 forceCoeffs_object
identifier (user given)
87 {
88 type forceCoeffs;
89 functionObjectLibs ("libforces.so");
90
91 enabled true;
92
93 patches ("wall_slat" "wall_airfoil" "wall_flap");
94
95 pName p;
96 Uname U;
97
99 rho rhoInf;
100 rhoInf 1.0;
101
103 log true;
104
105 CofR (0.0 0 0);
106
107 pitchAxis (0 0 1);
108 magUInf 1.0;
109 lRef 1;
110 Aref 1;
111
115 writeControl timeStep;
116 writeInterval 1;
117 • Reference axes to compute the lift and drag coefficients.
119 liftDir (0 1 0);
120 dragDir (1 0 0); • Remember, lift and drag are perpendicular and parallel
121
125 } to the incoming flow, respectively.
24 probes_online
• probes functionObject
25 {
26 type probes; • This functionObject is used to probe field data at the
27 functionObjectLibs ("libfieldFunctionObjects.so"); given locations.
28 enabled true;
29 writeControl timeStep; • In this case, we are sampling the fields U and p (lines 35-
30 writeInterval 1;
31 39)
32 probeLocations
33 ( • The output of this functionObject is saved in ascii format
34 (1 0 0) in the files p and U located in the directory
35 (2 0 0)
36 (2 0.25 0)
postProcessing/probes_online/0
37 (2 -0.25 0)
38 );
39 • Remember, the name of the directory where the output
40 fields data is saved is the same as the name of the
41 (
42 U
functionObject (line 19).
43 p
44 );
45
46 } • vorticity functionObject
52 vorticity • This functionObject is used to compute the vorticity field.
53 {
54 type vorticity; • The output of this functionObject is saved in the solution
55 functionObjectLibs ("libfieldFunctionObjects.so");
56 enabled true;
directories (1, 2, 3, and so on). You can visualize this
57 log true; output using paraview/paraFoam.
58 writeControl outputTime;
59 }
530
On-the-fly postprocessing – functionObjects
Final remarks on functionObjects
• A functionObject that is very useful, but we did not use in this case:
inlet_massflow
{
type surfaceRegion;
functionObjectLibs ("libfieldFunctionObjects.so");
writeControl timeStep;
writesInterval 1;
log true;
Compute functionObject in a boundary patch
writeFields false;
regionType patch;
name inlet;
operation sum;
Compute functionObject in this boundary patch
fields (phi);
}
• This functionObject is used to computed the mass flow across a boundary patch.
• Remember, the method is conservative so what is going in, is going out (unless you have
source terms).
• So if you want to measure the mass imbalance, setup this function object for each boundary
patch where you have flow entering or going out of the domain.
531
On-the-fly postprocessing – functionObjects
Final remarks on functionObjects
532
On-the-fly postprocessing – functionObjects
Running functionObjects a-posteriori
• Sometimes it can happen that you forget to use a functionObject or you want to execute a
functionObject a-posteriori (when the simulation is over).
• The solution to this problem is to use the solver with the option -postProcess. This will only
compute the new functionObject, it will not rerun the simulation.
• For instance, let us say that you forgot to use a given functionObject. Open the dictionary
controlDict, add the new functionObject, and type in the terminal,
• $> name_of_the_solver -postProcess –dict dictionary_location
• You also have the option of adding the new functionObject in an external file. If you chose this
option, do not forget to add the functionOption within the function sub-dictionary block:
function
{
//functionObject definitions here
};
• By proceeding in this way you do not need to rerun the simulation, you just compute the new
functionObject.
533
On-the-fly postprocessing – functionObjects
Running functionObjects a-posteriori
• In the directory system, you will find the following functionObject external
dictionaries: externalFunctionObject
• To run this functionObject a-posteriori, type in the terminal:
535
Roadmap
536
Sampling with the postProcess utility
• OpenFOAM® provides the postProcess utility to sample field data for plotting.
• The sampling parameters are specified in a dictionary located in the case system
directory.
• You can give any name to the input dictionary, hereafter we are going to name them
sampleDict (to sample along a line) and probesDict (to sample in a set of
probes).
• During the sampling, and inside the case directory, a new directory named
postProcessing will be created. In this directory, the sampled values are stored in
a sub-directory with the name of the input dictionary, in this case, sampleDict and
probesDict.
• This utility can sample points, lines, and surfaces.
• Data can be written in a range of formats including well-known plotting packages
such as: grace/xmgr, gnuplot and jPlot.
• The sampling can be executed by running the utility postProcess in the case
directory and according to the application syntax.
• A final word, this utility does not do the sampling while the solver is running. It does
the sampling after you finish the simulation.
537
Sampling with the postProcess utility
• To do sampling, we will use the solution from the previous case.
• If you do not have the solution, follow the instructions given in the previous slides.
• Hereafter, we will sample along a line and in a few probe locations, as illustrated in
the figure below.
538
Sampling with the postProcess utility
Running the case
539
Sampling with the postProcess utility
The sampleDict and probesDict dictionaries
• These dictionaries are located in the directory system.
• In this case, the sampleDict dictionary is used to sample along a line. This file
contains several entries to be set according to the user needs. The following entries
can be set,
• The choice of the interpolationScheme.
• The format of the line data output.
• The format of the surface data output.
• The fields to be sample.
• The sub-dictionaries that controls each sampling operation.
• In these sub-dictionaries you can set the name, type and geometrical
information of the sampling operation.
• In this case, the probesDict is used to sample in a set of points. This file contains
several entries to be set according to the user needs. The following entries,
• The fields to be sample.
• Location of the probes.
• The following functionObjects type can be used to do sampling: patchProbes,
probes, sets, or surfaces.
540
Sampling with the postProcess utility
The sampleDict dictionary
Note:
66 );
Use the banana method to know all the options available. 541
Sampling with the postProcess utility
The sampleDict dictionary
48 }
66 );
542
Sampling with the postProcess utility
The probesDict dictionary
20 (
21 p
22 U Fields to sample. No need to mention that they must exist.
23 );
27 probeLocations
28 (
29 (1.0 0 0)
30 (1.25 0 0)
31 (1.5 0 0)
32 (1.75 0 0)
33 (2.0 0 0) Location of the points.
34 (2.0 -.25 0)
35 (2.0 -.5 0)
36 (2.0 .25 0)
37 (2.0 .5 0)
38 );
Note:
Use the banana method to know all the options available. 543
Sampling with the postProcess utility
The probesDict dictionary
544
Sampling with the postProcess utility
The output files – functionObject type sets or surfaces
Scalars
#POINT_COORDINATES (X Y Z) SCALAR_VALUE
0 0 0.05 13.310995
0 0 0.1 19.293817
…
Vectors
#POINT_COORDINATES (X Y Z) VECTOR_COMPONENTS (X Y Z)
0 0 0.05 0 0 2.807395
0 0 0.1 0 0 2.826176
…
545
Sampling with the postProcess utility
The output files – functionObject type sets or surfaces
Scalars
#AXIS_COORDINATE SCALAR_VALUE
0 18.594038
0.0015 18.249091
…
Vectors
#AXIS_COORDINATE VECTOR_COMPONENTS (X Y Z)
0 0 0 1.6152966
0.0015 0 0 1.8067536
…
546
Sampling with the postProcess utility
The output files – functionObject type sets or surfaces
Scalars
#POINT_COORDINATES (X Y Z) SCALAR_VALUE
0 0 0.05 13.310995
0 0 0.1 19.293817
…
Vectors
#POINT_COORDINATES (X Y Z) VECTOR_COMPONENTS (X Y Z)
0 0 0.05 0 0 2.807395
0 0 0.1 0 0 2.826176
…
547
Sampling with the postProcess utility
The output files – functionObject type probes
Scalars
# Probe 0 (0 0 0.025)
# Probe 1 (0 0 0.05)
# Probe 2 (0 0 0.075)
# Probe 3 (0 0 0.1)
# Probe 0 1 2 3
# Time
0 0 0 0 0
0.005 19.1928 16.9497 14.2011 11.7580
0.01 16.6152 14.5294 12.1733 10.0789
…
…
…
548
Sampling with the postProcess utility
The output files – functionObject type probes
Vectors
# Probe 0 (0 0 0.025)
# Probe 1 (0 0 0.05)
# Probe 2 (0 0 0.075)
# Probe 3 (0 0 0.1)
# Probe 0 1 2 3
# Time
0 (0 0 0) (0 0 0) (0 0 0) (0 0 0)
0.005 (0 0 2.1927) (0 0 2.1927) (0 0 2.1927) (0 0 2.1927)
0.01 (0 0 2.5334) (0 0 2.5334) (0 0 2.5334) (0 0 2.5334)
…
…
…
549
Sampling with the postProcess utility
Exercises
• Where is located the source code of the utility postProcess?
• Try to do the sampling in parallel? Does it run? What about the output file?
• How many options are there available to do sampling in a line?
• Do point, line, and surface sampling using paraFoam/ParaView and compare with the output of the
postProcess utility. Do you get the same results?
• Compute the descriptive statistics of each column of the output files using gnuplot. Be careful with the
parentheses of the vector files.
(Hint: you can use sed within gnuplot)
550
Roadmap
551
Field manipulation
• Hereafter we are going to deal with field manipulation
• Field manipulation means modifying a field variable or deriving a new field
variable using the primitive variables computed during the solution stage.
• We will do the post-processing using the command line interface (CLI), or
non-GUI mode.
• The utility postProcess can be used as a single application, e.g.,
• $> postProcess –func vorticity
• Running the solver with the option –postprocess will only execute the
post-processing and it will let you access data available on the database for
the particular solver (such as physical properties or turbulence model).
552
Field manipulation
• To get a list of what can be computed using the postProcess utility, type in
the terminal:
• $> postProcess –list
• The utility postProcess can take many options. To get more information
on how to use the utility, type in the terminal:
• $> postProcess –help
• $> simpleFoam -postProcess –help
• The options of the solver using the –postProcess flag are the same as the
options of the utility postProcess.
• In the sub-directory $FOAM_UTILITIES/postProcessing/postProcess
you will find the utility postProcess.
• In the directory $FOAM_SRC/functionObjects, you will find the source
code of the objects that can be used to compute a new field.
553
Field manipulation
$PTOFC/101postprocessing/supersonic_wedge/
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
554
Field manipulation
After computing the solution, we can compute derived fields (e.g., Mach number, density,
Courant number, vorticity, and so on), using the primitive fields (U, p, T)
Mach number Total pressure
555
Field manipulation
What are we going to do?
• We will use this case to introduce the postProcess utility for field manipulation.
• We will also show how to run the solver with the option -postProcess. This will let us do only
the post-processing after the solution has been computed, and it will let us access the database
of the solver.
• To find the numerical solution we will use the solver rhoPimpleFoam.
• rhoPimpleFoam is a transient solver for laminar or turbulent flow of compressible gas.
1. $> sh run_solver.sh
2. $> paraFoam
• Fell free to open the file run_solver.sh to know all the steps.
556
Field manipulation
• After finding the solution, we can compute the new field variables using the
primitive variables computed during the solution stage. In the terminal type:
558
Field manipulation
• After finding the solution, we can compute new field variables using the primitive
variables computed during the solution stage. In the terminal type:
• We can also use the utility postProcess to compute the average and integral of a
specified field over a patch. In the terminal type:
560
Roadmap
561
Data conversion
• OpenFOAM® gives users a lot of flexibility when it comes to scientific visualization.
• You are not obliged to use OpenFOAM® visualization tools (paraFoam or paraview).
• You can convert the solution obtained with OpenFOAM® to many third-party formats
by using OpenFOAM® data conversion utilities.
• If you are looking for a specific format and it is not supported, you can write your own
conversion tool.
• In the directory $FOAM_UTILITIES/postProcessing/dataConversion, you will
find the source code of the following data conversion utilities:
• foamDataToFluent • foamToTecplot360
• foamToEnsight • foamToTetDualMesh
• foamToEnsightParts • foamToVTK
• foamToGMV • smapToFoam
• To get more information on how to use a data conversion utility, you can read the
source code or type in the terminal:
• $> name_of_data_conversion_utility -help
562
Data conversion
ASCII ↔ Binary conversion
• Another utility that might come in handy, specially when dealing with
large meshes is foamFormatConvert.
17
18
application icoFoam; • This utility converts the mesh and field variables into ascii or binary
19 startFrom startTime; format.
20
21 startTime 0; • In order to manually edit the boundary file and the field variables
22
23 stopAt endTime; dictionaries (initial and boundary conditions), they must be in ascii
24
25 endTime 50; format.
26
27 deltaT 0.01; • After editing these files, we can convert them into binary format.
28
29
30
writeControl runTime;
• Working in binary format can significantly reduce data parsing and
31 writeInterval 1; dimension of the files (specially for large meshes).
32
33
34
purgeWrite 0;
• The drawback is that the files are not human readable anymore.
35 writeFormat binary;
36 • To convert ascii files into binary files, just type in the terminal:
37 writePrecision 8;
38 • $> foamFormatConvert
39 writeCompression off;
40
41 timeFormat general; • Remember you will need to set the keyword writeFormat to binary
42
43 timePrecision 6;
in the controlDict dictionary.
44
45 runTimeModifiable true; • In the same way, if you want to convert from binary to ascii, set the
keyword writeFormat to ascii in the controlDict dictionary and
type in the terminal:
• $> foamFormatConvert
563
Module 6
Finite volume method overview
564
Roadmap
565
Finite Volume Method: A Crash introduction
• This a brief introduction to the FVM to illustrate some basic concepts.
• There is much more under the hood.
• We will use the general transport equation as the starting point to explain the FVM,
• Starting from this equation, we can write down the Navier-Stokes equations (NSE).
• So everything we are going to address also applies to the NSE or any set of
equations that can be derived form the general transport equation.
566
Finite Volume Method: A Crash introduction
• This a brief introduction to the FVM to illustrate some basic concepts.
• There is much more under the hood.
• We will use the general transport equation as the starting point to explain the FVM,
Problem statement
• Find the approximate solution to the general transport equation for the transported
quantity in a given domain, with given boundary conditions (BC) and initial
conditions (IC).
• It is an initial boundary value problem (IBVP).
• This is a second order equation. Therefore, for good accuracy, it is necessary that
the order of the discretization is equal or higher than the order of the equation that is
being discretized (in space and time).
567
Finite Volume Method: A Crash introduction
• Let us use the general transport equation as the starting point to explain the FVM,
• Hereafter we are going to assume that the discretization practice is at least second
order accurate in space and time.
• As consequence of the previous requirement, all dependent variables are assumed
to vary linearly around a point P in space and instant t in time,
Profile assumptions using Taylor expansions around point P (in space) and point t (in time)
568
Finite Volume Method: A Crash introduction
Domain discretization – Mesh information and variable arrangement
• Domain discretization (or mesh generation), consist in dividing the solution domain into a finite
number of arbitrary control volumes or cells, such as the one illustrated below.
• Inside each control volume the solution is sought.
• The control volumes can be of any shape (e.g., tetrahedrons, hexes, prisms, pyramids,
dodecahedrons, and so on). The only requirement is that the faces that made up the control
volume need to be planar.
• We also know which control volumes are internal and which control volumes lie on the
boundaries.
569
Finite Volume Method: A Crash introduction
Domain discretization – Mesh information and variable arrangement
• In the control volume illustrated, the centroid P and face center f are known.
• We also assume that the values of all variables are computed and stored in the centroid of the
control volume Vp and that they are represented by a piecewise constant profile (the mean
value),
570
Finite Volume Method: A Crash introduction
Domain discretization – Mesh information and variable arrangement
• Putting all together, it is a lot geometrical information that we need to track.
• A lot of overhead goes into the data book-keeping.
• At the end of the day, the FVM simply consist in conservation of the transported quantities and
interpolating information from cell centers to face centers.
Summary:
• The control volume has a volume V and is constructed
around point P, which is the centroid of the control volume.
Therefore the notation .
• The vector from the centroid P of to the centroid N of the
neighboring control volume is named d.
• We also know all neighbors of the control volume
• The control volume faces are labeled f, which also denotes the
face center.
• The location where the vector d intersects a face is .
• The face area vector point outwards from the control
volume, is located at the face centroid, is normal to the face and
has a magnitude equal to the area of the face.
• The vector from the centroid P to the face center f is named Pf.
571
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Let us recall the Gauss or Divergence theorem,
572
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Let us use the Gauss theorem to convert the volume integrals into surface integrals,
• At this point the problem reduces to interpolating somehow the cell centered values (known
quantities) to the face centers.
• That is, we need to compute the gradient terms, source terms, and convective and diffusive
fluxes across the faces. 573
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Integrating in space each term of the general transport equation and by using Gauss theorem,
yields to the following discrete equations for each term
Convective term:
By using Gauss theorem we convert volume where we have approximated the integrant by means of
integrals into surface integrals the mid point rule, which is second order accurate
Gauss theorem:
574
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Integrating in space each term of the general transport equation and by using Gauss theorem,
yields to the following discrete equations for each term
Diffusive term:
By using Gauss theorem we convert volume where we have approximated the integrant by means of
integrals into surface integrals the mid point rule, which is second order accurate
Gauss theorem:
575
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Integrating in space each term of the general transport equation and by using Gauss theorem,
yields to the following discrete equations for each term
Gradient term:
where we have approximated the centroid gradients by using the Gauss theorem.
This method is second order accurate and is known as Gauss cell-based.
Gauss theorem:
Note:
• There are more methods for gradients
computation, e.g., least squares, node-
based reconstruction, and so on.
• As there is some algebra involved, we
do not provide the demonstration.
576
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Integrating in space each term of the general transport equation and by using Gauss theorem,
yields to the following discrete equations for each term
Source term:
This approximation is exact if is either constant or varies linearly within the control volume; otherwise is
second order accurate.
Sc is the constant part of the source term and Sp is the non-linear part
Gauss theorem:
577
Finite Volume Method: A Crash introduction
Gauss theorem and face fluxes computation
• Using the previous equations to evaluate the general transport equation over all the control
volumes, we obtain the following semi-discrete equation
• And recall that all variables are computed and stored at the centroid of the control volumes.
• The face values appearing in the convective and diffusive fluxes have to be computed by
some form of interpolation from the centroid values of the control volumes at both sides of
face f.
578
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes
• By looking the figure below, the face values appearing in the convective flux can be computed
as follows,
• This type of interpolation scheme is known as linear interpolation or central differencing and it is
second order accurate.
• However, it may generate oscillatory solutions (unbounded solutions).
579
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes
• By looking the figure below, the face values appearing in the convective flux can be computed
as follows,
• This type of interpolation scheme is known as upwind differencing and it is first order accurate.
• This scheme is bounded (non-oscillatory) and diffusive.
580
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes
• By looking the figure below, the face values appearing in the convective flux can be computed
as follows,
• This type of interpolation scheme is known as second order upwind differencing (SOU), linear
upwind differencing (LUD) or Beam-Warming (BW), and it is second order accurate.
• For highly convective flows or in the presence of strong gradients, this scheme is oscillatory
(unbounded).
581
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes
• To prevent oscillations in the SOU, we add a gradient or slope limiter function .
• When the limiter detects strong gradients or changes in slope, it switches locally to low
resolution (upwind).
• The concept of the limiter function is based on monitoring the ratio of successive
gradients, e.g.,
582
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – TVD schemes
583
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – TVD schemes
• Let us see how the upwind, linear upwind, linear, and Minmod TVD schemes behave in a
numerical schemes killer test case:
• The oblique double step profile in a uniform vector field (pure convection).
• Even if this problem seems to be easy, from the numerical point of view is difficult to resolve due
to the strong discontinuities.
• This problem has an exact solution.
584
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – TVD schemes
• Qualitative comparison of the upwind, linear upwind, linear, and Minmod TVD schemes
Upwind – 1st order Linear – 2nd order Linear Upwind – 2nd order
Very bounded but too Diffusive Very accurate but too oscillatory Bounded and accurate
SuperBee – TVD high resolution Minmod – TVD high resolution vanLeer – TVD high resolution
Compressive Diffusive Smooth
585
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – TVD schemes
• Quantitative comparison of the upwind, linear upwind, linear, and Minmod TVD schemes
586
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Unstructured meshes
• In the previous explanation, we assumed a line structure (figure A). That is, the cell centers PP,
P, and N are all aligned.
• In unstructured meshes (which are often used in industrial cases), most of the times the cell
center PP is not aligned with the vector connecting cells P and N (figure B). Therefore,
extending the previous formulations to these meshes is not very straightforward.
• Higher-order schemes for unstructured meshes are an area of active research, and new ideas
continue to emerge.
587
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Unstructured meshes
• A simple way around this problem is to redefine
higher-order schemes in terms of gradients at the
control volume P.
• For example, using the gradient of the cells, we can
compute the face values as follows,
Upwind →
Central difference →
• Notice that in this new formulation the cell PP does not appear anymore.
• The problem now turns in the accurate evaluation of the gradients at the cell and face centers.
• For example, the gradients at the cell centers can be computed using the Gauss method, and
then interpolated to the face centers.
• At this point, we are only missing the reconstruction of the cell center gradients at the face
centers, this is explained latter. 588
Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Unstructured meshes
• In unstructured meshes, as often the value of the node PP (of NN) is not available or
straightforward to compute, the ratio of successive gradients r can be computed as follows [1],
U → Upwind
D → Downwind
Reference:
[1] Darwish, M. S., Moukalled, F., “TVD schemes for unstructured grids” 589
Finite Volume Method: A Crash introduction
Gradients computation at cell centers
• There are many methods for the computation of the cell centered gradients, e.g., least squares,
Gauss cell-based, Gauss node-based, and so on.
• Using the Gauss cell-based method, the cell centered gradients can be computed as follows,
• This approximation is second order accurate given that the mesh quality is acceptable, and the
volume of the cell is finite.
• In general, the least squares method tends to be more accurate.
590
Finite Volume Method: A Crash introduction
Gradients reconstruction at face centers
• Face gradients arise from the discretization process of the convective and diffusive terms.
• One way to reconstruct the face gradient , is by using weighted interpolation of the cell
centered quantities and .
• Mesh non-orthogonality and skewness introduce errors when approximating the face gradients,
so corrections need to be added.
• This is an iterative process, where we compute successively better approximations to the
gradients starting from an initial approximation.
where
Face gradient
591
Finite Volume Method: A Crash introduction
Interpolation of diffusive fluxes in an orthogonal mesh
• By looking the figure below, the face values • By looking the figure below, the face values
appearing in the diffusive flux in an orthogonal appearing in the diffusive flux in a non-orthogonal
mesh can be computed as follows, mesh (20°) can be computed as follows,
• This is a central difference approximation of the • This type of approximation is second order accurate
first order derivative. This type of but involves a larger truncation error. It also uses a
approximation is second order accurate. larger numerical stencil, which make it less stable.
• Remember, the non-orthogonal angle is the angle between the vector S and the vector d
592
Finite Volume Method: A Crash introduction
Correction of diffusive fluxes in a non-orthogonal mesh
• By looking the figures below, the face values appearing in the diffusive flux in a non-orthogonal
mesh ( ) can be computed as follows.
• Using the over-relaxed approach, the diffusive fluxes can be corrected as follow,
Over-relaxed approach
593
Finite Volume Method: A Crash introduction
Mesh induced errors
• In order to maintain second order accuracy, and to avoid unboundedness, we need to correct
non-orthogonality and skewness errors.
• The ideal case is to have an orthogonal and non skew mesh, but this is the exception rather
than the rule.
Orthogonal and non skew mesh Non-orthogonal and non skew mesh
• After spatial discretization, we can proceed with the temporal discretization. By proceeding
in this way we are using the Method of Lines (MOL).
• The main advantage of the MOL method, is that it allows us to select numerical
approximations of different accuracy for the spatial and temporal terms. Each term can be
treated differently to yield to different accuracies.
595
Finite Volume Method: A Crash introduction
Temporal discretization
• Now, we evaluate in time the semi-discrete general transport equation
• At this stage, we can use any time discretization scheme, e.g., Crank-Nicolson, euler implicit,
forward euler, backward differencing, adams-bashforth, adams-moulton.
• It should be noted that the order of the temporal discretization of the transient term does not
need to be the same as the order of the discretization of the spatial terms.
• Each term can be treated differently to yield different accuracies. As long as the individual terms
are at least second order accurate, the overall accuracy will also be second order.
596
Finite Volume Method: A Crash introduction
Linear system solution
• After spatial and temporal discretization and by using equation
in every control volume of the domain, a system of linear algebraic equations for the
transported quantity is assembled,
• This system can be solved by using any iterative or direct method. 597
Finite Volume Method: A Crash introduction
So, what does OpenFOAM® do?
• It simply discretize in space and time the governing equations in arbitrary polyhedral control
volumes over the whole domain.
• Assembling in this way a large set of linear discrete algebraic equations (DAE), and then it solves
this system of DAE to find the solution of the transported quantities.
• Therefore, we need to give to OpenFOAM® the following information:
• Discretization of the solution domain or the mesh.
• This information is contained in the directory constant/polyMesh
• Boundary conditions and initials conditions.
• This information is contained in the directory 0
• Physical properties such as density, gravity, diffusion coefficient, viscosity, etc.
• This information is contained in the directory constant
• Physics involve, such as turbulence modeling, mass transfer, source terms, dynamic
meshes, multiphase models, combustion models, etc.
• This information is contained in the directories constant and/or system
598
Finite Volume Method: A Crash introduction
So, what does OpenFOAM® do?
• Therefore, we need to give to OpenFOAM® the following information:
• How to discretize in space each term of the governing equations (diffusive, convective,
gradient and source terms).
• This information is set in the system/fvSchemes dictionary.
• How to discretize in time the obtained semi-discrete governing equations.
• This information is set in the system/fvSchemes dictionary.
• How to solve the linear system of discrete algebraic equations (crunch numbers).
• This information is set in the system/fvSolution dictionary.
• Set runtime parameters and general instructions on how to run the case (such as time step,
maximum CFL number, solution saving frequency, and so on).
• This information is set in the system/controlDict dictionary.
• Additionally, we may set sampling and monitors for post-processing (functionObjects).
• This information is set in the system/fvSchemes dictionary or in the specific
sampling dictionaries located in the directory system/
599
Finite Volume Method: A Crash introduction
Where do we set all the discretization schemes in OpenFOAM®?
ddtSchemes • The fvSchemes dictionary contains the information related to
{ the discretization schemes for the different terms appearing in
default backward;
}
the governing equations.
gradSchemes
• The discretization schemes can be chosen in a term-by-term
{ basis.
default Gauss linear;
grad(p) Gauss linear; • The keyword ddtSchemes refers to the time discretization.
}
• The keyword gradSchemes refers to the gradient term
divSchemes discretization.
{
default none; • The keyword divSchemes refers to the convective term
div(phi,U) Gauss linear; discretization.
}
• The keyword laplacianSchemes refers to the Laplacian term
laplacianSchemes
{
discretization.
default Gauss linear orthogonal; • The keyword interpolationSchemes refers to the method used
}
to interpolate values from cell centers to face centers. It is
interpolationSchemes unlikely that you will need to use something different from
{ linear.
default linear;
} • The keyword snGradSchemes refers to the discretization of
snGradSchemes
the surface normal gradients evaluated at the faces.
{
default orthogonal;
• Remember, if you want to know the options available for each
} keyword you can use the banana method.
600
Finite Volume Method: A Crash introduction
Time discretization schemes
• There are many time discretization schemes available in OpenFOAM®.
• You will find the source code in the following directory:
• $WM_PROJECT_DIR/src/finiteVolume/finiteVolume/ddtSchemes
• These are the time discretization schemes that you will use most of the times:
• steadyState: for steady state simulations (implicit/explicit).
• Euler: time dependent first order (implicit/explicit), bounded.
• backward: time dependent second order (implicit), bounded/unbounded.
• CrankNicolson: time dependent second order (implicit), bounded/unbounded.
601
Finite Volume Method: A Crash introduction
Time discretization schemes
• The Crank-Nicolson method as it is implemented in OpenFOAM®, uses a blending factor.
ddtSchemes
{
default CrankNicolson ;
}
• Setting to 0 is equivalent to running a pure Euler scheme (robust but first order accurate).
• By setting the blending factor equal to 1 you use a pure Crank-Nicolson (accurate but
oscillatory, formally second order accurate).
• If you set the blending factor to 0.5, you get something in between first order accuracy and
second order accuracy, or in other words, you get the best of both worlds.
• A blending factor of 0.7-0.9 is safe to use for most applications (stable and accurate).
602
Finite Volume Method: A Crash introduction
Convective terms discretization schemes
• There are many convective terms discretization schemes available in OpenFOAM® (more than
50 last time we checked).
• You will find the source code in the following directory:
• $WM_PROJECT_DIR/src/finiteVolume/interpolation/surfaceInterpolation
• These are the convective discretization schemes that you will use most of the times:
• upwind: first order accurate.
• linearUpwind: second order accurate, bounded.
• linear: second order accurate, unbounded.
• A good TVD scheme (vanLeer or Minmod): TVD, second order accurate, bounded.
• limitedLinear: second order accurate, unbounded, but more stable than pure linear.
Recommended for LES simulations (kind of similar to the Fromm method).
• LUST: blended 75% linear and 25% linearUpwind scheme
gradSchemes
{
grad(U) cellMDLimited Gauss linear 1.0;
}
divSchemes
{
div(phi,U) Gauss linearUpwind grad(U);
}
604
Finite Volume Method: A Crash introduction
Gradient terms discretization schemes
• There are many gradient discretization schemes available in OpenFOAM®.
• You will find the source code in the following directory:
• $WM_PROJECT_DIR/src/finiteVolume/finiteVolume/gradSchemes
• These are the gradient discretization schemes that you will use most of the times:
• Gauss linear (cell-based method)
• Gauss pointLinear (node-based method; more accurate than the cell-based method)
• leastSquares
• To avoid overshoots or undershoots when computing the gradients, you can use gradient
limiters.
• Gradient limiters increase the stability of the method but add diffusion due to clipping.
• You will find the source code in the following directory:
• $WM_PROJECT_DIR/src/finiteVolume/finiteVolume/gradSchemes/limitedGradSchemes
• These are the most important gradient limiter schemes available in OpenFOAM®:
• cellLimited, cellMDLimited, faceLimited, faceMDLimited
• All of the gradient discretization schemes are at least second order accurate.
605
Finite Volume Method: A Crash introduction
Gradient terms discretization schemes
• These are the gradient limiter schemes available in OpenFOAM®:
gradSchemes
{
default cellLimited Gauss linear ;
}
• Setting to 0 is equivalent to turning off the gradient limiter. You gain accuracy but the solution
might become unbounded.
• By setting the blending factor equal to 1 the limiter is set to be very aggressive (kind of saying
that it is always on). You gain stability but you give up accuracy (due to gradient clipping).
• If you set the blending factor to 0.5, you get the best of both worlds.
• You can use limiters with all gradient discretization schemes.
607
Finite Volume Method: A Crash introduction
Laplacian terms discretization schemes
• There are many Laplacian terms discretization schemes available in OpenFOAM®.
• You will find the source code in the following directory:
• $WM_PROJECT_DIR/src/finiteVolume/finiteVolume/snGradSchemes
• These are the Laplacian terms discretization schemes that you will
use most of the times:
• orthogonal: mainly limited for hexahedral meshes with no
grading (a perfect mesh). Second order accurate, bounded
on perfect meshes, without non-orthogonal corrections.
• corrected: for meshes with grading and non-orthogonality. Can be computed using the over-relaxed approach
Only option
laplacianSchemes
{
default Gauss linear limited ;
}
Interpolation method of the diffusion coefficient
• Setting to 1 is equivalent to using the corrected method. You gain accuracy, but the solution might
become unbounded.
• By setting the blending factor equal to 0 is equivalent to using the uncorrected method. You give up accuracy
but gain stability.
• If you set the blending factor to 0.5, you get the best of both worlds. In this case, the non-orthogonal
contribution does not exceed the orthogonal part. You give up accuracy but gain stability.
• For meshes with non-orthogonality less than 70, you can set the blending factor to 1.
• For meshes with non-orthogonality between 70 and 85, you can set the blending factor to 0.5
• For meshes with non-orthogonality more than 85, it is better to get a better mesh. But if you want to use that
mesh, you can set the blending factor to 0.333-0.5, and increase the number of non-orthogonal corrections.
• If you are doing LES or DES simulations, use a blending factor of 1 (this means that you need good meshes). 609
Finite Volume Method: A Crash introduction
Laplacian terms discretization schemes
• Just to make it clear, the blending factor is used to avoid the non-orthogonal contribution
exceeding the orthogonal part.
• That is, non-orthogonal contribution ≤ orthogonal contribution.
The blending factor works as a limiter acting on this term (non-orthogonal contribution)
• In meshes with large non-orthogonality, the explicit term can lead to unboundedness and
eventually divergence.
• This limiting is local, similar to the treatment done for the connective terms when using slope
limiters and TVD schemes.
• The explicit contribution is added to the RHS of the linear system (source term), so if this term
becomes too large it will lead to convergence problems.
• It becomes harder to guarantee diagonal dominance of the matrix of coefficient.
610
Finite Volume Method: A Crash introduction
Laplacian terms discretization schemes
• The surface normal gradients terms usually use the same method as the one chosen for the
Laplacian terms.
• For instance, if you are using the limited 1 method for the Laplacian terms, you can use the
same method for snGradSchemes:
laplacianSchemes
{
default Gauss linear limited 1;
}
snGradSchemes
{
default limited 1;
}
611
Finite Volume Method: A Crash introduction
What method should I use?
ddtSchemes • This setup is recommended for most of
{
default CrankNicolson 0;
the cases.
}
gradSchemes • It is equivalent to the default method you will find in
{ commercial solvers.
default cellLimited Gauss linear 0.5;
grad(U) cellLimited Gauss linear 1; • In overall, this setup is second order accurate and
}
divSchemes
fully bounded.
{
default none;
• According to the quality of your mesh, you will need
div(phi,U) Gauss linearUpwindV grad(U); to change the blending factor of the
div(phi,omega) Gauss linearUpwind default; laplacianSchemes and snGradSchemes
div(phi,k) Gauss linearUpwind default;
keywords.
div((nuEff*dev(T(grad(U))))) Gauss linear;
}
laplacianSchemes
• To keep temporal diffusion to a minimum, use a CFL
{ number less than 2, and preferably below 1.
default Gauss linear limited 1;
} • If during the simulation the turbulence quantities
interpolationSchemes
{
become unbounded, you can safely change the
default linear; discretization scheme to upwind. After all,
}
snGradSchemes
turbulence is diffusion.
{
default limited 1; • For gradient discretization the leastSquares
} method is more accurate. But we have found that it
is a little bit oscillatory in tetrahedral meshes.
612
Finite Volume Method: A Crash introduction
A very accurate but oscillatory numerics
ddtSchemes • If you are looking for more accuracy, you can use
{
default backward;
this method.
}
gradSchemes • In overall, this setup is second order accurate but
{ oscillatory.
default Gauss leastSquares;
} • Use this setup with LES simulations or laminar
divSchemes
{ flows with no complex physics and meshes with
default none; overall good quality.
div(phi,U) Gauss linear;
div(phi,omega) Gauss limitedlinear 1; • Use this method with good quality meshes.
div(phi,k) Gauss limitedLinear 1;
div((nuEff*dev(T(grad(U))))) Gauss linear; • According to the quality of your mesh, you will need
}
laplacianSchemes
to change the blending factor of the
{ laplacianSchemes and snGradSchemes
default Gauss linear limited 1; keywords.
}
interpolationSchemes
{
default linear;
}
snGradSchemes
{
default limited 1;
}
613
Finite Volume Method: A Crash introduction
A very stable but too diffusive numerics
ddtSchemes • If you are looking for extra stability, you can use this
{
default Euler;
method.
}
gradSchemes • This setup is very stable but too diffusive.
{
default cellLimited Gauss linear 1; • This setup is first order in space and time.
grad(U) cellLimited Gauss linear 1;
}
• You can use this setup to start the solution in the
divSchemes presence of bad quality meshes or strong
{
default none;
discontinuities.
div(phi,U) Gauss upwind;
• Remember, you can start using a first order method
div(phi,omega) Gauss upwind;
div(phi,k) Gauss upwind; and then switch to a second order method.
div((nuEff*dev(T(grad(U))))) Gauss linear;
} • According to the quality of your mesh, you will need
laplacianSchemes to change the blending factor of the
{
default Gauss linear limited 0.5; laplacianSchemes and snGradSchemes
} keywords.
interpolationSchemes
{ • Start robustly, end with accuracy.
default linear;
}
snGradSchemes
• You can use this method for troubleshooting. If the
{ solution diverges, you better check boundary
}
default limited 0.5;
conditions, physical properties, and so on.
614
Roadmap
615
On the CFL number
• First of all, what is the CFL or Courant number?
• In one dimension, the CFL number is defined as,
• By the way, and this is extremely important, the CFL condition is a necessary
condition for stability (and hence convergence).
• But it is not always sufficient to guarantee stability.
• Other properties of the discretization schemes that you should observe are:
conservationess, boundedness, transportiveness, and accuracy.
618
On the CFL number
How to control the CFL number
application pimpleFoam; • You can control the CFL number by changing the mesh cell
size or changing the time-step size.
startFrom latestTime;
maxCo 2.0;
maxDeltaT 0.001;
619
On the CFL number
How to control the CFL number
application pimpleFoam; • The option adjustTimeStep will automatically adjust the time
step to achieve the maximum desired courant number
startFrom latestTime;
(maxCo) or time-step size (maxDeltaT).
startTime 0;
stopAt endTime;
• When any of these conditions is reached, the solver will stop
scaling the time-step size.
endTime 10;
deltaT 0.0001;
• To use these features, you need to turn-on the option
adjustTimeStep.
writeControl runTime;
writeInterval 0.1;
• Remember, the first time-step of the simulation is done using
the value defined with the keyword deltaT and then it is
purgeWrite 0;
automatically scaled (up or down), to achieve the desired
writeFormat ascii; maximum values (maxCo and maxDeltaT).
writePrecision 8;
• It is recommended to start the simulation with a low time-step
writeCompression off;
in order to let the solver scale-up the time-step size.
timeFormat general;
• If you want to change the values on-the-fly, you need to turn-
timePrecision 6;
on the option runTimeModifiable.
runTimeModifiable yes;
• The feature adjustTimeStep is only present in the PIMPLE
adjustTimeStep yes;
family solvers, but it can be added to any solver by modifying
maxCo 2.0; the source code.
maxDeltaT 0.001;
620
On the CFL number
The output screen
• This is the output screen of a solver supporting the option adjustTimeStep.
• In this case maxCo is equal 2 and maxDeltaT is equal to 0.001.
• Notice that the solver reached the maximum allowable maxDeltaT.
Courant Number mean: 0.10863988 max: 0.73950028 Courant number (mean and maximum values)
deltaT = 0.001 Current time-step
Time = 30.000289542261612 Simulation time
PIMPLE: iteration 1 One PIMPLE iteration (outer loop), this is equivalent to PISO
DILUPBiCG: Solving for Ux, Initial residual = 0.003190933, Final residual = 1.0207483e-09, No Iterations 5
DILUPBiCG: Solving for Uy, Initial residual = 0.0049140114, Final residual = 8.5790109e-10, No Iterations 5
DILUPBiCG: Solving for Uz, Initial residual = 0.010705877, Final residual = 3.5464756e-09, No Iterations 4
GAMG: Solving for p, Initial residual = 0.024334674, Final residual = 0.0005180308, No Iterations 3
GAMG: Solving for p, Initial residual = 0.00051825089, Final residual = 1.6415538e-05, No Iterations 5
time step continuity errors : sum local = 8.768064e-10, global = 9.8389717e-11, cumulative = -2.6474162e-07
GAMG: Solving for p, Initial residual = 0.00087813032, Final residual = 1.6222017e-05, No Iterations 3
GAMG: Solving for p, Initial residual = 1.6217958e-05, Final residual = 6.4475277e-06, No Iterations 1
time step continuity errors : sum local = 3.4456296e-10, global = 2.6009599e-12, cumulative = -2.6473902e-07
ExecutionTime = 33091.06 s ClockTime = 33214 s
CPU time and wall clock
fieldMinMax domainminandmax output:
min(p) = -0.59404715 at location (-0.019 0.02082288 0.072) on processor 1
max(p) = 0.18373302 at location (-0.02083962 -0.003 -0.136) on processor 1
min(U) = (0.29583255 -0.4833922 -0.0048229716) at location (-0.02259661 -0.02082288 -0.072) on processor 0
max(U) = (0.59710937 0.32913292 0.020043679) at location (0.11338793 -0.03267608 0.12) on processor 3
min(nut) = 1.6594481e-10 at location (0.009 -0.02 0.024) on processor 0
max(nut) = 0.00014588174 at location (-0.02083962 0.019 0.072) on processor 1
622
Linear solvers in OpenFOAM®
• After spatial and temporal discretization and by using equation
in every control volume of the domain, a system of linear algebraic equations for the
transported quantity is assembled
624
Linear solvers in OpenFOAM®
Linear solvers – fvSolution dictionary
solvers • In this generic case, to solve the pressure (p) we are using the
{ PCG method with the DIC preconditioner, an absolute
p
{
tolerance equal to 1e-06 and a relative tolerance relTol equal
solver PCG; to 0.
preconditioner DIC;
tolerance 1e-06; • The entry pFinal refers to the final pressure correction (notice
relTol 0; that we are using macro syntax), and we are using a relative
}
tolerance relTol equal to 0 (disabled).
pFinal
{ • To solve the velocity field (U) we are using the PBiCGStab
$p; method with the DILU preconditoner, an absolute tolerance
relTol 0;
}
equal to 1e-08 and a relative tolerance relTol equal to 0.
U
{
• The linear solvers will iterative until reaching any of the
solver PBiCGStab; tolerance values set by the user or reaching a maximum value
preconditioner DILU; of iterations (optional entry).
tolerance 1e-08;
relTol 0; • FYI, solving for the velocity is relatively inexpensive, whereas
} solving for the pressure is expensive.
}
• The pressure equation is particularly important as it governs
PISO mass conservation.
{
nCorrectors 2; • If you do not solve the equations accurately enough (tolerance),
nNonOrthogonalCorrectors 1;
the physics might be wrong.
}
• Selection of the tolerance is of paramount importance and it
might be problem dependent.
625
Linear solvers in OpenFOAM®
Linear solvers – fvSolution dictionary
solvers • The linear solvers are iterative, i.e., they are based on reducing
{ the equation residual over a succession of solutions.
p
{ • The residual is a measure of the error in the solution so that the
solver PCG;
preconditioner DIC;
smaller it is, the more accurate the solution.
tolerance 1e-06;
• More precisely, the residual is evaluated by substituting the
relTol 0;
} current solution into the equation and taking the magnitude of
pFinal the difference between the left- and right-hand sides (L2-norm).
{
$p;
relTol 0;
}
U
{
solver PBiCGStab;
preconditioner DILU;
• It is also normalized to make it independent of the scale of the
tolerance 1e-08; problem being analyzed.
relTol 0;
}
}
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
626
Linear solvers in OpenFOAM®
Linear solvers – fvSolution dictionary
solvers • Before solving an equation for a particular field, the initial
{ residual is evaluated based on the current values of the field.
p
{ • After each solver iteration the residual is re-evaluated. The
solver PCG;
preconditioner DIC;
solver stops if either of the following conditions are reached:
tolerance 1e-06;
• The residual falls below the solver tolerance, tolerance.
relTol 0;
} • The ratio of current to initial residuals falls below the solver
pFinal
{ relative tolerance, relTol.
$p; • The number of iterations exceeds a maximum number of
relTol 0;
}
iterations, maxIter.
U
{
• The solver tolerance should represent the level at which the
solver PBiCGStab; residual is small enough that the solution can be deemed
preconditioner DILU; sufficiently accurate.
tolerance 1e-08;
relTol 0; • The keyword maxIter is optional and the default value is 1000.
minIter 3;
maxIter 100; • The user can also define the minimum number of iterations
} using the keyword minIter. This keyword is optional, and the
}
default value is 0.
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
627
Linear solvers in OpenFOAM®
Linear solvers
• These are the linear solvers (segregated) available in OpenFOAM®:
• You will find the source code of the linear solvers in the following directory:
• $WM_PROJECT_DIR/src/OpenFOAM/matrices/lduMatrix/solvers
Time = 50
630
Linear solvers in OpenFOAM®
Linear solvers tolerances
• So how do we set the tolerances?
• The pressure equation is particularly important, so we should resolve it accurately. Solving the
pressure equation is the expensive part of the whole iterative process.
• For the pressure equation (symmetric matrix), you can start the simulation with a tolerance
equal to 1e-6 and relTol equal to 0.01.
• And after a while, you change these values to 1e-6 and 0.0, respectively.
• If the linear solver is taking too much time, you can change the convergence criterion to 1e-4
and relTol equal to 0.05. You usually will do this during the first iterations.
p p
{ {
solver PCG; solver PCG;
preconditioner DIC; preconditioner DIC;
tolerance 1e-6; tolerance 1e-6;
relTol 0.01; relTol 0.0;
} }
631
Linear solvers in OpenFOAM®
Linear solvers tolerances
• For the velocity field (U) and the transported quantities (asymmetric matrices), you can use the
following criterion.
• Solving for these variables is relatively inexpensive, so you can start right away with a tight
tolerance.
• As a side note, the relative tolerance (relTol) is the difference between the initial residuals and
the current final residuals.
U U
{ {
solver PBiCGStab; solver PBiCGStab;
preconditioner DILU; preconditioner DILU;
tolerance 1e-8; tolerance 1e-8;
relTol 0.001; relTol 0.0;
} }
632
Linear solvers in OpenFOAM®
Linear solvers tolerances
• It is also a good idea to set the minimum number of iterations (minIter), we recommend using a
value of 3.
• If your solver is doing too many iterations, you can set the maximum number of iterations
(maxIter).
• But be careful, if the solver reach the maximum number of iterations it will stop, we are talking
about unconverged time-steps or outer-iterations.
• Setting the maximum number of iterations is especially useful during the first time-steps where
the linear solver takes longer to converge.
• You can set minIter and maxIter in all symmetric and asymmetric linear solvers.
p
{
solver PCG;
preconditioner DIC;
tolerance 1e-6;
relTol 0.01;
minIter 3;
maxIter 100;
}
633
Linear solvers in OpenFOAM®
Linear solvers tolerances
• When you use the PISO or PIMPLE method with the momentumPredictor option (which is
enabled by default), you also have the option to set the tolerance for the final pressure corrector
step (pFinal).
• By proceeding in this way, you can put all the computational effort only in the last corrector step
(pFinal).
• For all the intermediate corrector steps, you can use a more relaxed convergence criterion.
• For example, you can use the following solver and tolerance criterion for all the intermediate
corrector steps (p), then in the final corrector step (pFinal) you tight the solver tolerance.
p pFinal
{ {
solver PCG; solver PCG;
preconditioner DIC; preconditioner DIC;
tolerance 1e-4; tolerance 1e-6;
relTol 0.05; relTol 0.0;
} }
634
Linear solvers in OpenFOAM®
Linear solvers tolerances
• When you use the PISO or PIMPLE method with the momentumPredictor option (which is
enabled by default), you also have the option to set the tolerance for the final pressure corrector
step (pFinal).
• By proceeding in this way, you can put all the computational effort only in the last corrector step
(pFinal in this case).
• For all the intermediate corrector steps (p), you can use a more relaxed convergence criterion.
• If you proceed in this way, it is recommended to do at least 2 corrector steps (nCorrectors).
PIMPLE: iteration 1
DILUPBiCG: Solving for Ux, Initial residual = 0.0024649332, Final residual = 2.3403547e-09, No Iterations 4
DILUPBiCG: Solving for Uy, Initial residual = 0.0044355904, Final residual = 1.8966277e-09, No Iterations 4
DILUPBiCG: Solving for Uz, Initial residual = 0.010100894, Final residual = 1.4724403e-09, No Iterations 4
GAMG: Solving for p, Initial residual = 0.018497918, Final residual = 0.00058090899, No Iterations 3
1 p
GAMG: Solving for p, Initial residual = 0.00058090857, Final residual = 2.5748489e-05, No Iterations 5
time step continuity errors : sum local = 1.2367812e-09, global = 2.8865505e-11, cumulative = 1.057806e-08
GAMG: Solving for p, Initial residual = 0.00076032002, Final residual = 2.3965621e-05, No Iterations 3 p
2 GAMG: Solving for p, Initial residual = 2.3961044e-05, Final residual = 6.3151172e-06, No Iterations 2 pFinal
time step continuity errors : sum local = 3.0345314e-10, global = -3.0075104e-12, cumulative = 1.0575052e-08
DILUPBiCG: Solving for omega, Initial residual = 0.00073937735, Final residual = 1.2839908e-10, No Iterations 4
DILUPBiCG: Solving for k, Initial residual = 0.0018291502, Final residual = 8.5494234e-09, No Iterations 3
ExecutionTime = 29544.18 s ClockTime = 29600 s
nCorrectors
635
Linear solvers in OpenFOAM®
Linear solvers – Matrix reordering
• As we are solving a sparse matrix, the more diagonal the matrix is, the best the convergence
rate will be.
• So it is highly advisable to use the utility renumberMesh before running the simulation.
• $> renumberMesh –overwrite
• The utility renumberMesh can dramatically increase the speed of the linear solvers, specially
during the first iterations.
• The idea behind reordering is to make the matrix more diagonally dominant, therefore, speeding
up the iterative solver.
Matrix structure plot before reordering Matrix structure plot after reordering
Note: this is the actual pressure matrix from an OpenFOAM® model case 636
Linear solvers in OpenFOAM®
On the multigrid solvers
• The development of multigrid solvers (GAMG in OpenFOAM®), together with the development
of high-resolution TVD schemes and parallel computing, are among the most remarkable
achievements of the history of CFD.
• Most of the time using the GAMG linear solver is fine.
• However, if you see that the GAMG linear solver is taking too long to converge or is converging
in more than 100 iterations, it is better to use the PCG linear solver.
• Particularly, we have found that the GAMG linear solver in OpenFOAM® does not perform very
well when you scale your computations to more than 500 processors.
• Also, we have found that for some multiphase cases the PCG method outperforms the GAMG.
• But again, this is problem and hardware dependent.
• As you can see, you need to always monitor your simulations (stick to the screen for a while.
• Otherwise, you might end-up using a solver that is performing poorly, and this translate in
increased computational time and costs.
637
Linear solvers in OpenFOAM®
On the multigrid solvers tolerances
• If you go for the GAMG linear solver for symmetric matrices (e.g., pressure), the following
tolerances are acceptable for most of the cases.
p pFinal
{ {
solver GAMG; solver GAMG;
tolerance 1e-6; tolerance 1e-6;
relTol 0.01; relTol 0;
smoother GaussSeidel; smoother GaussSeidel;
nPreSweeps 0; nPreSweeps 0;
nPostSweeps 2; nPostSweeps 2;
cacheAgglomeration on; cacheAgglomeration on;
agglomerator faceAreaPair; agglomerator faceAreaPair;
nCellsInCoarsestLevel 100; nCellsInCoarsestLevel 100;
mergeLevels 1; mergeLevels 1;
minIter 3; minIter 3;
} }
NOTE:
The GAMG parameters are not optimized, that is up to you.
Most of the times is safe to use the proposed parameters.
638
Linear solvers in OpenFOAM®
Linear solvers tolerances – Steady simulations
• The previous tolerances are fine for unsteady solver.
• For extremely coupled problems you might need to have tighter tolerances.
• You can use the same tolerances for steady solvers. However, it is acceptable to use a looser
criterion.
• For steady simulations using the SIMPLE method, you can set the convergence controls based
on residuals of fields.
• The controls are specified in the residualControls sub-dictionary of the dictionary file
fvSolution.
SIMPLE
{
nNonOrthogonalCorrectors 2;
residualControl
{
p 1e-4; Residual control for every
U 1e-4; field variable you are solving
}
}
639
Linear solvers in OpenFOAM®
Linear solvers benchmarking of a model case
641
Roadmap
642
Pressure-Velocity coupling in OpenFOAM®
• To solve the Navier-Stokes equations we need to use a solution approach able to
deal with the nonlinearities of the governing equations and with the coupled set of
equations.
643
Pressure-Velocity coupling in OpenFOAM®
• Many numerical methods exist to solve the Navier-Stokes equations, just to name a
few:
• Pressure-correction methods (Predictor-Corrector type).
• SIMPLE, SIMPLEC, SIMPLER, PISO.
• Projection methods.
• Fractional step (operator splitting), MAC, SOLA.
• Density-based methods and preconditioned solvers.
• Riemann solvers, ROE, HLLC, AUSM+, ENO, WENO.
• Artificial compressibility methods.
• Artificial viscosity methods.
• The most widely used approaches for solving the NSE are:
• Pressure-based approach (predictor-corrector).
• Density-based approach.
644
Pressure-Velocity coupling in OpenFOAM®
• Historically speaking, the pressure-based approach was developed for low-speed
incompressible flows, while the density-based approach was mainly developed for
high-speed compressible flows.
• However, both methods have been extended and reformulated to solve and operate
for a wide range of flow conditions beyond their original intent.
• In OpenFOAM®, you will find segregated pressure-based solvers.
• The segregated pressure-based solvers in OpenFOAM®, solve a modified pressure
equation (pressure-Poisson equation).
• The following methods are available:
• SIMPLE (Semi-Implicit Method for Pressure-Linked Equations)
• SIMPLEC (SIMPLE Corrected/Consistent)
• PISO (Pressure Implicit with Splitting Operators)
• You will find the solvers in the following directory:
• $WM_PROJECT_DIR/applications/solvers
• Additionally, you will find something called PIMPLE, which is a hybrid between
SIMPLE and PISO (known as iterative PISO outside OpenFOAM® jargon).
• This formulation can give you more accuracy and stability when using very
large time-steps or in pseudo-transient simulations.
645
Pressure-Velocity coupling in OpenFOAM®
• In OpenFOAM®, the PISO and PIMPLE methods are formulated for unsteady
simulations.
• Whereas, the SIMPLE and SIMPLEC methods are formulated for steady simulations.
• If conserving time is not a priority, you can use the PIMPLE method in pseudo
transient mode.
• The pseudo transient PIMPLE method is more stable than the SIMPLE method, but it
has a higher computational cost.
• Also, the pseudo transient PIMPLE method tends to be faster than the fully transient
PIMPLE when reaching steady states.
• Depending on the method and solver you are using, you will need to define a specific
sub-dictionary in the dictionary file fvSolution.
• For instance, if you are using the PISO method, you will need to specify the PISO
sub-dictionary.
• And depending on the method, each sub-dictionary will have different entries.
646
Pressure-Velocity coupling in OpenFOAM®
On the origins of the methods
• SIMPLE
• S. V. Patankar and D. B. Spalding, “A calculation procedure for heat, mass and momentum
transfer in three-dimensional parabolic flows”, Int. J. Heat Mass Transfer, 15, 1787-1806 (1972).
• SIMPLE-C
• J. P. Van Doormaal and G. D. Raithby, “Enhancements of the SIMPLE method for predicting
incompressible fluid flows”, Numerical Heat Transfer, 7, 147-163 (1984).
• PISO
• R. I. Issa, “Solution of the implicitly discretized fluid flow equations by operator-splitting”, J.
Comput. Phys., 62, 40-65 (1985).
• PIMPLE
• Unknown origins outside OpenFOAM® ecosystem (we are referring to the semantics).
• It is equivalent to PISO with outer iterations (iterative time-advancement of the solution).
• Useful reference (besides PISO reference):
• I. E. Barton, “Comparison of SIMPLE and PISO-type algorithms for transient flows, Int. J.
Numerical methods in fluids, 26,459-483 (1998).
• P. Oliveira and R. I. Issa, “An improved piso algorithm for the computation of buoyancy-driven
flows”, Numerical Heat Transfer, 40, 473-493 (2001).
647
Pressure-Velocity coupling in OpenFOAM®
The SIMPLE sub-dictionary
• This sub-dictionary is located in the dictionary file fvSolution.
• It controls the options related to the SIMPLE pressure-velocity coupling method.
• The SIMPLE method only makes one correction.
• An additional correction to account for mesh non-orthogonality is available when using the
SIMPLE method. The number of non-orthogonal correctors is specified by the
nNonOrthogonalCorrectors keyword.
• The number of non-orthogonal correctors is chosen according to the mesh quality.
• For orthogonal meshes you can use 0 non-orthogonal corrections. However, it is strongly
recommended to do at least 1 non-orthogonal correction (this helps stabilizing the solution).
• For non-orthogonal meshes, it is recommended to do at least 1 correction.
SIMPLE
{
nNonOrthogonalCorrectors 1;
}
648
Pressure-Velocity coupling in OpenFOAM®
The SIMPLE sub-dictionary
• You can use the optional keyword consistent to enable or disable the SIMPLEC method.
• This option is disable by default.
• In the SIMPLEC method, the cost per iteration is marginally higher but the convergence rate is
better, so the number of iterations is reduced.
• The SIMPLEC method relaxes the pressure in a consistent manner and additional relaxation of
the pressure is not generally necessary (but it is recommended).
• In addition, convergence of the p-U system is better and still is reliable with less aggressive
relaxation factors of the momentum equation.
SIMPLE
{
consistent yes;
nNonOrthogonalCorrectors 1;
}
649
Pressure-Velocity coupling in OpenFOAM®
The SIMPLE sub-dictionary
• These are the typical (or industry standard) under-relaxation factors for the SIMPLE and
SIMPLEC methods.
• Remember the under-relaxation factors are problem dependent.
SIMPLE SIMPLEC
relaxationFactors relaxationFactors
{ {
fields fields
{ {
p 0.3; p 1.0;
} } Usually there is no need
to under-relax pressure;
equations equations however, it is advisable.
{ {
U 0.7; p 1.0;
k 0.7; U 0.9;
omega 0.7; k 0.9;
} omega 0.9;
} }
}
650
Pressure-Velocity coupling in OpenFOAM®
The SIMPLE sub-dictionary
SIMPLEC
relaxationFactors
• If you are planning to use the SIMPLEC method,
{
we recommend you to use under-relaxation factors
that are little bit more smaller that the industry fields
standard values. {
p 0.7;
• If during the simulation you still have some stability
}
problems, try to reduce all the values to 0.5.
equations
• Remember the under-relaxation factors are {
problem dependent. p 0.7;
• If you are having convergence problems, it is U 0.7;
recommended to start the simulation with low k 0.7;
values (about 0.3), and then increase the values omega 0.7;
slowly up to 0.7 or 0.9 (for faster convergence). }
}
651
Pressure-Velocity coupling in OpenFOAM®
The SIMPLE loop in OpenFOAM®
fvVectorMatrix UEqn
(
fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U)
);
solve(UEqn == -fvc::grad(p));
fvScalarMatrix pEqn
(
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
);
U = HbyA – rAU*fvc::grad(p);
652
Pressure-Velocity coupling in OpenFOAM®
The PISO sub-dictionary
• This sub-dictionary is located in the dictionary file fvSolution.
• It controls the options related to the PISO pressure-velocity coupling method.
• The PISO method requires at least one correction (nCorrectors).
• For good accuracy and stability (specially in unstructured meshes), it is recommended to use at
least 2 nCorrectors.
• An additional correction to account for mesh non-orthogonality is available when using the PISO
method. The number of non-orthogonal correctors is specified by the
nNonOrthogonalCorrectors keyword.
• The number of non-orthogonal correctors is chosen according to the mesh quality.
• For orthogonal meshes you can use 0 non-orthogonal corrections. However, it is strongly
recommended to do at least 1 non-orthogonal correction (this helps stabilizing the solution).
• For non-orthogonal meshes, it is recommended to do at least 1 correction.
PISO
{
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
653
Pressure-Velocity coupling in OpenFOAM®
The PISO sub-dictionary
• You can use the optional keyword momentumPredictor to enable or disable the momentum
predictor step.
• The momentum predictor helps in stabilizing the solution as we are computing better
approximations for the velocity.
• It is clear that this will add an extra computational cost, which most of the times is negligible.
• In most of the solvers, this option is enabled by default.
• It is recommended to use this option for highly convective flows (high Reynolds number). If you
are working with low Reynolds flow or creeping flows it is recommended to turn it off.
• Note that when you enable the option momentumPredictor, you will need to define the linear
solvers for the variables .*Final (we are using regex notation).
• Also, if you want to use URF you will need to apply then to all field variables (including .*Final).
PISO
{
momentumPredictor yes;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
654
Pressure-Velocity coupling in OpenFOAM®
The PISO loop in OpenFOAM®
(PISO with non-iterative marching – NITA – )
fvVectorMatrix UEqn
(
fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U)
);
solve(UEqn == -fvc::grad(p));
fvScalarMatrix pEqn
(
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
);
U = HbyA – rAU*fvc::grad(p);
PIMPLE
{
momentumPredictor yes;
nOuterCorrectors 1;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
656
Pressure-Velocity coupling in OpenFOAM®
The PIMPLE sub-dictionary
• You can use under-relaxation factors (URF) with the PIMPLE solvers.
• By using URF, you will gain more stability in time dependent solutions (as they control the amount of change of
field variables within the time-step).
• However, if you use too low URF values, your solution might not be time-accurate anymore.
• You can use the same or larger URF values as those for steady simulation.
• Note that when you enable the option momentumPredictor, you will need to define the linear solvers for the
variables .*Final (we are using regex notation).
• You can assign URF to all variables (including .*Final), to only the intermediate field variables (U, p, k, and so
on), or to only the .*Final variables (UFinal, pFinal, kFinal, and so on).
• We recommend to use URF in all variables.
PIMPLE
{
momentumPredictor yes;
nOuterCorrectors 1;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
657
Pressure-Velocity coupling in OpenFOAM®
The PIMPLE loop in OpenFOAM®
(PISO with iterative marching – ITA – )
fvVectorMatrix UEqn
(
fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U)
);
solve(UEqn == -fvc::grad(p));
fvScalarMatrix pEqn
(
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
);
U = HbyA – rAU*fvc::grad(p);
658
Pressure-Velocity coupling in OpenFOAM®
Comparison of PISO with non-iterative time-advancement (PISO-NITA)
against PISO with Iterative time-advancement (PISO-ITA)
• The main difference between both methods is the outer loop present in the PISO-ITA.
• This outer loop gives more stability and allow the use of very large time-steps (CFL numbers).
• The recommended CFL number of the PISO-NITA is below 2 (for good accuracy and stability).
660
Unsteady and steady simulations
Sliding grids – Continuous stirred tank reactor
• Nearly all flows in nature and industrial applications www.wolfdynamics.com/wiki/FVM_uns/ani5.gif
are unsteady (also known as transient or
time-dependent).
• Unsteadiness can be due to:
• Instabilities.
• Non-equilibrium initial conditions.
• Time-dependent boundary conditions. Multiphase flow
www.wolfdynamics.com/wiki/FVM_uns/ani3.gif
• Source terms.
• Chemical reactions and finite rate chemistry.
• Phase change.
• Moving or deforming bodies.
• Turbulence.
• Buoyancy and heat transfer.
• Discontinuities.
Turbulent flows - SRS
• Multiple phases. www.wolfdynamics.com/wiki/FVM_uns/ani4.gif
661
Unsteady and steady simulations
How to run unsteady simulations in OpenFOAM®?
• Select the time step. The time-step must be chosen in such a way that it resolves the time-dependent features
and maintains solver stability.
• Select the temporal discretization scheme.
• Set the tolerance (absolute and/or relative) of the linear solvers.
• Monitor the CFL number.
• Monitor the stability and boundedness of the solution.
• Monitor a quantity of interest.
• And of course, you need to save the solution with a given frequency.
• Have in mind that unsteady simulations generate a lot of data.
• End time of the simulation?, it is up to you.
• In the controlDict dictionary you need to set runtime parameters and general instructions on how to run the
case (such as time step and maximum CFL number). You also set the saving frequency.
• In the fvSchemes dictionary you need to set the temporal discretization scheme.
• In the fvSolution dictionary you need to set the linear solvers.
• Also, you will need to set the number of corrections of the velocity-pressure coupling method used (e.g. PISO
or PIMPLE), this is done in the fvSolution dictionary.
• Additionally, you may set functionObjects in the controlDict dictionary. The functionObjects are used to
do sampling, probing and co-processing while the simulation is running.
662
Unsteady and steady simulations
How to run unsteady simulations in OpenFOAM®?
divSchemes
{
default none;
div(phi,U) Gauss linear;
}
laplacianSchemes
{
default Gauss linear orthogonal;
}
interpolationSchemes
{
default linear;
}
snGradSchemes
{
default orthogonal;
}
663
Unsteady and steady simulations
How to run unsteady simulations in OpenFOAM®?
writeControl runTime; • It will write the solution every 0.1 seconds (writeInterval) of
simulation time (runTime).
writeInterval 0.1;
• The time step of the simulation is 0.0001 seconds (deltaT).
purgeWrite 0;
• It will keep all the solution directories (purgeWrite).
writeFormat ascii;
• It will save the solution in ascii format (writeFormat) with a
writePrecision 8; precision of 8 digits (writePrecision).
writeCompression off; • And as the option runTimeModifiable is on (yes), we can
modify all these entries while we are running the simulation.
timeFormat general;
• To reduce parsing time and file size, it is recommended to use
timePrecision 6;
binary format to write the solution.
runTimeModifiable yes;
adjustTimeStep yes;
maxCo 2.0;
maxDeltaT 0.001;
664
Unsteady and steady simulations
How to run unsteady simulations in OpenFOAM®?
startFrom latestTime; • In this generic case, the solver supports adjustable time-step
(adjustTimeStep).
startTime 0;
• The option adjustTimeStep will automatically adjust the time
stopAt endTime;
step to achieve the maximum desired courant number (maxCo)
endTime 10; or time-step size (maxDeltaT).
deltaT 0.0001; • When any of these conditions is reached, the solver will stop
scaling the time-step size.
writeControl runTime;
• Remember, the first time-step of the simulation is done using the
writeInterval 0.1; value defined with the keyword deltaT and then it is
purgeWrite 0;
automatically scaled (up or down), to achieve the desired
maximum values (maxCo and maxDeltaT).
writeFormat ascii;
• It is recommended to start the simulation with a low time-step in
writePrecision 8; order to let the solver scale-up the time-step size.
writeCompression off; • The feature adjustTimeStep is only present in the PIMPLE
family solvers, but it can be added to any solver by modifying
timeFormat general;
the source code.
timePrecision 6;
• If you are planning to use large time steps (CFL much higher
runTimeModifiable yes; than 1), it is recommended to do at least 3 correctors steps
(nCorrectors) in PISO/PIMPLE loop, and at least 2 outer
adjustTimeStep yes;
maxCo 2.0;
correctors in the PIMPLE loop.
maxDeltaT 0.001;
665
Unsteady and steady simulations
How to run unsteady simulations in OpenFOAM®?
solvers • The fvSolution dictionary contains the instructions of how to
{
p
solve each discretized linear equation system.
{ • As for the controlDict and fvSchemes dictionaries, the
solver PCG;
preconditioner DIC; parameters can be changed on-the-fly.
tolerance 1e-06;
relTol 0; • To set these parameters, follow the guidelines given in the
} previous section.
pFinal
• Depending on the solver you are using, you will need to define
{ the sub-dictionary PISO or PIMPLE.
$p;
• Setting the keyword nOuterCorrectors to 1 in PIMPLE solvers
relTol 0;
} is equivalent to running using the PISO method.
• To gain more stability, especially when using large time-steps,
“U.*”
{
you can use more outer correctors (nOuterCorrectors).
solver smoothSolver;
• If you are using large time steps (CFL much higher than 1), it is
smoother symGaussSeidel;
tolerance 1e-08; recommended to do at least 3 correctors steps (nCorrectors) in
relTol 0; PISO/PIMPLE loop.
}
} • Remember, in both PISO and PIMPLE method you need to do
PIMPLE at least one correction (nCorrectors).
{
nOuterCorrectors 1; • Adding corrections increase the computational cost
nCorrectors 2;
nNonOrthogonalCorrectors 1;
(nOuterCorrectors and nCorrectors).
}
666
Unsteady and steady simulations
How to choose the time-step in unsteady simulations and monitor the solution
• Remember, when running unsteady simulations the time-step must be chosen in such a way
that it resolves the time-dependent features and maintains solver stability.
667
Unsteady and steady simulations
Monitoring unsteady simulations
• When running unsteady simulations, it is highly advisable to monitor a quantity of interest.
• The quantity of interest can fluctuate in time, this is an indication of unsteadiness.
668
Unsteady and steady simulations
What about steady simulations?
• First of all, steady simulations are a big simplification of reality.
• Steady simulations is a trick used by CFDers to get fast outcomes with results that might be
even more questionable.
• Remember, most of the flows you will encounter are unsteady so be careful of this hypothesis.
• In steady simulations, we made two assumptions:
• We ignore unsteady fluctuations. That is, we neglect the time derivative in the governing
equations.
• We perform time averaging when dealing with stationary turbulence (RANS modeling)
• The advantage of steady simulations is that they require low computational resources, give fast
outputs, and are easier to post-process and analyze.
• To do so, you need to use the appropriate solver and use the right discretization scheme.
• As you are not solving the time derivative, you do not need to set the time step. However, you
need to tell OpenFOAM® how many iterations you would like to run.
• You can also set the residual controls (residualControl), in the fvSolution dictionary file.
You set the residualControl in the SIMPLE sub-dictionary.
• If you do not set the residual controls, OpenFOAM® will run until reaching the maximum
number of iterations (endTime).
669
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
• In the controlDict dictionary you need to set runtime parameters and general instructions on
how to run the case (such as the number of iterations to run).
• Remember to set also the saving frequency.
• In the fvSchemes dictionary you need to set the time discretization scheme, for steady
simulations it must be steadyState.
• In the fvSolution dictionary you need to set the linear solvers, under-relaxation factors, and
residual controls.
• Also, you will need to set the number of corrections of the velocity-pressure coupling method
used (e.g. SIMPLE or SIMPLEC), this is done in the fvSolution dictionary.
• Additionally, you may set functionObjects in the controlDict dictionary.
• The functionObjects are used to do sampling, probing and co-processing while the simulation
is running.
670
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
• Under-relaxation is a feature typical of steady solvers using the SIMPLE family of methods.
• These are the URF commonly used with SIMPLE and SIMPLEC (industry standard),
SIMPLE SIMPLEC
U 0.7; U 0.9;
k 0.7; k 0.9;
omega 0.7; omega 0.9;
• According to the physics involved you will need to add more under-relaxation factors.
• Finding the right URF involved experience and some trial and error.
• Selecting the URF it is kind of equivalent to selecting the right time step.
• Many times, steady simulations diverge because of wrongly chosen URF. 671
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
• An optimum choice of under-relaxation factors is one that is small enough to ensure stable
computation but large enough to move the iterative process forward quickly.
• Under-relaxation can be implicit (equation in OpenFOAM) or explicit (field in OpenFOAM).
interpolationSchemes
{
default linear; • This term removes a component proportional to the continuity
}
error. This acts as a convergence aid to tend towards a bounded
snGradSchemes solution as the calculation proceeds.
{
default orthogonal; • At convergence, this term becomes zero and does not
} contribute to the final solution.
673
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
writeControl runTime; • This generic case starts from iteration 0 (startTime), and it will
run up to 10000 iterations (endTime).
writeInterval 100;
• It will write the solution every 100 iterations (writeInterval) of
purgeWrite 10; simulation time (runTime).
writeFormat ascii; • It will advance the solution one iteration at a time (deltaT).
writePrecision 8; • It will keep the last 10 saved solutions (purgeWrite).
writeCompression off; • It will save the solution in ascii format (writeFormat) with a
precision of 8 digits (writePrecision).
timeFormat general;
• And as the option runTimeModifiable is on (true), we can
timePrecision 6;
modify all these entries while we are running the simulation.
runTimeModifiable yes;
674
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
solvers • The fvSolution dictionary contains the instructions of how to
{
p
solve each discretized linear equation system.
{ • As for the controlDict and fvSchemes dictionaries, the
solver PCG;
preconditioner DIC; parameters can be changed on-the-fly.
tolerance 1e-06;
relTol 0; • To set these parameters, follow the guidelines given in the
} previous section.
U
• Increasing the number of nNonOrthogonalCorrectors
{ corrections will add more stability but at a higher computational
solver smoothSolver; cost.
smoother symGaussSeidel;
tolerance 1e-08; • Remember, nNonOrthogonalCorrectors is used to improve
relTol 0; the gradient computation due to mesh quality.
}
} • The SIMPLE sub-dictionary also contains convergence controls
based on residuals of fields. The controls are specified in the
SIMPLE
{
residualControls sub-dictionary.
nNonOrthogonalCorrectors 2;
• The user needs to specify a tolerance for one or more solved
residualControl fields and when the residual for every field falls below the
{ corresponding residual, the simulation terminates.
p 1e-4;
U 1e-4; • If you do not set the residualControls, the solver will iterate
} until reaching the maximum number of iterations set in the
}
controlDict dictionary.
675
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
• The fvSolution dictionary also contains the
relaxationFactors relaxationFactors sub-dictionary.
{
fields • The relaxationFactors sub-dictionary which controls under-
{ relaxation, is a technique used for improving stability when using
p 0.3;
}
steady solvers.
equations
{
• Under-relaxation works by limiting the amount which a variable
U 0.7; changes from one iteration to the next, either by modifying the
} solution matrix and source prior to solving for a field (equations
}
keyword) or by modifying the field directly (fields keyword).
• Under-relaxing the equations is also known as implicit under-
relaxation.
• Whereas, under-relaxing the fields is also known as explicit
under-relaxation.
• An optimum choice of under-relaxation factors is one that is
small enough to ensure stable computation but large enough to
move the iterative process forward quickly.
• In this case we are using the industry standard URF.
• Remember, URF are problem dependent.
• If you do not define URF, the solver will not under-relax.
676
Unsteady and steady simulations
How to run steady simulations in OpenFOAM®?
• To enable the consistent formulation of the SIMPLE method, you need to add the following
keywork to the SIMPLE sub-dictionary,
SIMPLE
{
Enabled/disabled consistent formulation of the
consistent yes; SIMPLE loop
nNonOrthogonalCorrectors 3;
}
678
Roadmap
679
Understanding residuals
• Before talking about residuals, let us clarify something.
• When we talk about iterations in unsteady simulations, we are talking about the time-step or
outer-iterations.
680
Understanding residuals
• To get a better idea of how iterative methods work, and what are initial residuals and final residuals, let us
take another look at a residual plot.
682
Understanding residuals
• Remember, residuals are not a direct indication that you are converging to the right solution.
• It is better to monitor a quantity of interest (QOI).
• And by the way, you should get physically realistic values.
• In this case, if you monitor the residuals you might get the impression that the simulation is diverging.
• Instead, if you monitor a QOI you will realize that there is an initial transient (long one by the way), then the
onset of an instability, and then a periodic behavior of the phenomenon.
• You should assess the convergence of the solution and compute the unsteady statistics in the time window
where the behavior of the QOI is periodic.
• To monitor the stability, you can check the minimum and maximum values of the field variables.
• If you have bounded quantities, check that you do not have over-shoots or under-shoots.
Residuals QOI
683
Understanding residuals
• This is the output of the residuals for all field • This is the output of the residuals for all field
variables of an unsteady case. variables of a steady case.
• Notice that at the beginning the residuals show a • The jumps are due to the changes in tolerance
monotonic behavior. introduced while running the simulation.
• Then, after a while the convergence rate changes. • As you can see, the residuals are falling in a
monotonic way.
• This not necessarily means that the solution is
diverging, it might be an indication of unsteadiness.
684
Understanding residuals
• This is the output of the aerodynamic • This is the output of the aerodynamic
coefficients for an unsteady case. coefficients for a steady case.
685
Roadmap
686
Boundary conditions and initial conditions
On the initial boundary value problem (IBVP)
• First of all, when we use a CFD solver to find the approximate solution of the governing
equations, we are solving an Initial Boundary Value Problem (IBVP).
• In an IBVP, we need to impose appropriate boundary conditions and initial conditions.
• No need to say that the boundary conditions and initial conditions need to be physically realistic.
• Boundary conditions are a required component of the numerical method, they tell the solver
what is going on at the boundaries of the domain.
• You can think of boundary conditions as source terms.
• Initial conditions are also a required component of the numerical method, they define the initial
state of the problem.
687
Boundary conditions and initial conditions
A few words about boundary conditions
• Boundary conditions (BC) can be divided into three fundamental mathematical types:
• Dirichlet boundary conditions: when we use this BC, we prescribe the value of a variable at the
boundary.
• Neumann boundary conditions: when we use this BC, we prescribe the gradient normal to the
boundary.
• Robin Boundary conditions: this BC is a mixed of Dirichlet boundary conditions and Neumann
boundary
• You can use any of these three boundary conditions in OpenFOAM®.
• During this discussion, the semantics is not important, that depends of how you want to call the BCs or how
they are named in the solver, i.e., in, inlet, inflow, velocity inlet, incoming flow and so on.
• Defining boundary conditions involves:
• Finding the location of the boundary condition in the domain.
• Determining the boundary condition type.
• Giving the required physical information.
• The choice of the boundary conditions depend on:
• Geometrical considerations.
• Physics involved.
• Information available at the boundary condition location.
• Numerical considerations.
• And most important, you need to understand the physics involved.
688
Boundary conditions and initial conditions
A few words about boundary conditions
• To define boundary conditions you need to know the location of the boundaries (where they are
in your mesh).
• You also need to supply the information at the boundaries.
• Last but not least important, you must know the physics involved.
689
Boundary conditions and initial conditions
A few words about initial conditions
• Initial conditions (IC) can be divided into two groups:
• Uniform initial conditions.
• Non-uniform initial conditions.
691
Boundary conditions and initial conditions
• Inlets and outlets boundary conditions:
• Inlets are for regions where inflow is expected; however, inlets might support outflow when
a velocity profile is specified.
• Pressure boundary conditions do not allow outflow at the inlets.
• Velocity specified inlets are intended for incompressible flows.
• Pressure and mass flow inlets are suitable for compressible and incompressible flows.
• Same concepts apply to outlets, which are regions where outflow is expected.
692
Boundary conditions and initial conditions
• Zero gradient (Neumann) and backflow boundary conditions:
• Zero gradient boundary conditions extrapolates the values from the domain. They require
no information.
• Zero gradient boundary conditions can be used at inlets, outlets, and walls.
• Backflow boundary conditions provide a generic outflow/inflow condition, with specified
inflow/outflow for the case of backflow.
• In the case of a backflow outlet, when the flux is positive (out of domain) it applies a
Neumann boundary condition (zero gradient), and when the flux is negative (into of
domain), it applies a Dirichlet boundary condition (fixed value).
• Same concept applies to backflow inlets.
693
Boundary conditions and initial conditions
• On the outlet pressure boundary condition
• Some combinations of boundary conditions are very stable, and some are less reliable.
• And some configurations are unreliable.
• Inlet velocity at the inlet and pressure zero gradient at the outlet. This combination
should be avoided because the static pressure level is not fixed.
• Qualitatively speaking, the results are very different.
• This simulation will eventually crash.
BCs 1. Inlet velocity and fixed outlet pressure BCs 2. Inlet velocity and zero gradient outlet pressure
www.wolfdynamics.com/wiki/BC/aniBC1.gif www.wolfdynamics.com/wiki/BC/aniBC2.gif
694
Boundary conditions and initial conditions
• On the outlet pressure boundary condition
• If you only rely on a QOI and the residuals, you will not see any major difference between
the two cases with different outlet pressure boundary condition.
• This is very misleading.
• However, when you visualize the solution you will realize that something is wrong. This is
a case where pretty pictures can be used to troubleshoot the solution.
• Quantitative speaking, the results are very similar.
• However, this simulation will eventually crash.
Residual plot for pressure Quantity of interest – Force coefficient on the body
695
Boundary conditions and initial conditions
• Symmetry boundary conditions:
• Symmetry boundary conditions are a big simplification of the problem. However, they help
to reduce mesh cell count.
• Have in mind that symmetry boundary conditions only apply to planar faces.
• To use symmetry boundary conditions, both the geometry and the flow field must be
symmetric.
• Mathematically speaking, setting a symmetry boundary condition is equivalent to zero
normal velocity at the symmetry plane, and zero normal gradients of all variables at the
symmetry plane.
• Physically speaking, they are equivalent to slip walls.
696
Boundary conditions and initial conditions
• Location of the outlet boundary condition:
• Place outlet boundary conditions as far as possible from recirculation zones or backflow
conditions, by doing this you increase the stability.
• Remember, backflow conditions requires special treatment.
Far enough so the flow can be
Possible backflow Might be OK
considered fully developed
697
Boundary conditions and initial conditions
• Domain dimensions (when the dimensions are not known):
• If you do not have any constrain in the domain dimensions, you can use as a general guideline the
dimensions illustrated in the figure below, where L is a reference length (in this case, L is the wing chord).
• The values illustrated in the figure are on the conservative side, nut if you want to play safe, multiply the
values by two or more.
• Always verify that there are no significant gradients normal to any of the boundaries patches. If there are,
you should consider increasing the domain dimensions.
698
Boundary conditions and initial conditions
A few considerations and guidelines
• Boundary conditions and initial conditions need to be physically realistic.
• Poorly defined boundary conditions can have a significant impact on your solution.
• Initial conditions are as important as the boundary conditions.
• A good initial condition can improve the stability and convergence rate.
• On the other hand, unphysical initial conditions can slow down the convergence rate or can cause divergence.
• You need to define boundary conditions and initials conditions for every single variable you are solving.
• Setting the right boundary conditions is extremely important, but you need to understand the physics.
• You need to understand the physics in order to set the right boundary conditions.
• Do not force the flow at the outlet, use a zero normal gradient for all flow variables except pressure. The solver
extrapolates the required information from the interior.
• Be careful with backward flow at the outlets (flow coming back to the domain) and backward flow at inlets
(reflection waves), they required special treatment.
• If possible, select inflow and outflow boundary conditions such that the flow either goes in or out normal to the
boundaries.
• At outlets, use zero gradient boundary conditions only with incompressible flows and when you are sure that the
flow is fully developed.
• Outlets that discharge to the atmosphere can use a static pressure boundary condition. This is interpreted as
the static pressure of the environment into which the flow exhausts.
699
Boundary conditions and initial conditions
A few considerations and guidelines
• Inlets that take flow into the domain from the atmosphere can use a total pressure boundary condition (e.g.
open window).
• Mass flow inlets produce a uniform velocity profile at the inlet.
• Pressure specified boundary conditions allow a natural velocity profile to develop.
• The required values of the boundary conditions and initial conditions depend on the equations you are solving,
and physical models used, e.g.,
• For incompressible and laminar flows you will need to set only the velocity and pressure.
• If you are solving a turbulent compressible flow you will need to set velocity, pressure, temperature and
the turbulent variables.
• For multiphase flows you will need to set the primitives variables for each phase. You will also need to
initialize the phases.
• If you are doing turbulent combustion or chemical reactions, you will need to define the species, reactions
and turbulent variables.
• Minimize grid skewness, non-orthogonality, growth rate, and aspect ratio near the boundaries. You do not want
to introduce diffusion errors early in the simulation, especially close to the inlets.
• Try to avoid large gradients in the direction normal to the boundaries and near inlets and outlets.
• That is to say, put your boundaries far away from where things are happening.
700
Boundary conditions and initial conditions
• OpenFOAM® distinguish between base type boundary conditions and numerical type
boundary conditions.
• Base type boundary conditions are based on geometry • Numerical type boundary condition assigns the value to the
information (surface patches) or on inter-processor field variables in the given surface patch.
communication link (halo boundaries).
• Numerical type boundary conditions are defined in the field
• Base type boundary conditions are defined in the file variables dictionaries located in the directory 0 (e.g. U, p).
boundary located in the directory constant/polyMesh
• When we talk about numerical type boundary conditions, we
• The file boundary is automatically created when you are referring to Dirichlet, Neumann or Robin boundary
generate or convert the mesh. conditions.
• When you convert a mesh to OpenFOAM® format, you • You need to manually create the field variables dictionaries
might need to manually modify the file boundary. This is (e.g. 0/U, 0/p, 0/T, 0/k, 0/omega).
because the conversion utilities do not recognize the
boundary type of the original mesh. • Remember, if you forget to define a numerical boundary
condition, OpenFOAM® will complain and will tell you where
• Remember, if a base type boundary condition is missing, and what is the error.
OpenFOAM® will complain and will tell you where and what
is the error. • Also, if you misspelled something OpenFOAM® will complain
and will tell you where and what is the error.
• Also, if you misspelled something OpenFOAM® will complain
and will tell you where and what is the error
701
Boundary conditions and initial conditions
• The following base type and numerical type boundary conditions are constrained or paired.
• That is, the type needs to be same in the boundary dictionary and field variables dictionaries
(e.g. 0/U, 0/p, 0/T, 0/k, 0/omega).
cyclic cyclic
cyclicAMI cyclicAMI
empty empty
processor processor
symmetry symmetry
symmetryPlane symmetryPlane
wedge wedge
advective
calculated
codedFixedValue
epsilonWallFunction
fixedValue
inletOutlet
movingWallVelocity
patch
rotatingWallVelocity
slip
supersonicFreeStream
totalPressure
zeroGradient
… and so on
Refer to the doxygen documentation or the source code for a list of all
numerical boundary conditions available.
703
Boundary conditions and initial conditions
• The wall base type boundary condition is defined as follows:
type fixedValue;
wall zeroGradient
value uniform (0 0 0);
• This boundary condition is not contained in the patch base type boundary conditions group,
because specialize modeling options can be used on this boundary condition.
• An example is turbulence modeling, where turbulence can be generated or dissipated at the
walls.
704
Boundary conditions and initial conditions
• To deal with backflow at outlets, you can use the following boundary condition:
type inletOutlet;
type fixedValue;
patch inletValue uniform (0 0 0);
value uniform 0;
value uniform (0 0 0);
705
Boundary conditions and initial conditions
• Typical boundary conditions are as follows (external aerodynamics),
* Wall functions can be: kqWallFunction, omegaWallFunction, nutkWallFunction, and so on (next slide).
706
Boundary conditions and initial conditions
• Typical wall functions boundary conditions are as follows,
zeroGradient or fixedValue 0 or
epsilon epsilonWallFunction
a small number
omegaWallFunction or
omega omegaWallFunction
fixedValue with a big number
707
Boundary conditions and initial conditions
• Finally, remember that the name of the base type boundary condition and the name of the
numerical type boundary condition needs to be the same, if not, OpenFOAM® will complain.
• Pay attention to this, specially if you are converting the mesh from another format.
• Also, do not use spaces of funny characters when assigning the names to the boundary
patches.
• The following names are consistent among all dictionary files,
708
Boundary conditions and initial conditions
• There is a plethora of boundary conditions implemented in OpenFOAM®.
• You can find the source code of the main numerical boundary conditions in the following directory:
• $WM_PROJECT_DIR/src/finiteVolume/fields/
• The wall boundary conditions for the turbulence models (wall functions), are located in the following directory:
• $WM_PROJECT_DIR/src/MomentumTransportModels/momentumTransportModels/derivedF
vPatchFields/wallFunctions
• To find all the boundary conditions implemented in OpenFOAM, go to the directory $WM_PROJECT_DIR and
type in the terminal,
• $> find . -type d -iname *fvPatch*
• To get more information about all the boundary conditions available in OpenFOAM® you can read the
Doxygen documentation.
3
(
movingWall
movingWall frontAndBack
{
type patch;
nFaces 20;
startFace 760;
}
fixedWalls
fixedWalls
fixedWalls
{
type wall;
nFaces 60;
startFace 780;
}
frontAndBack
{
type empty;
nFaces 800; frontAndBack
startFace 840;
}
fixedWalls
710
Boundary conditions and initial conditions
The constant/polyMesh/boundary dictionary
• For a generic case, the file boundary is divided as follows
movingWall
dimensions [0 1 -1 0 0 0 0]; type fixedValue;
value uniform (1 0 0);
internalField uniform (0 0 0);
boundaryField frontAndBack
{ type empty;
type fixedValue;
type fixedValue;
fixedWalls
type fixedValue;
fixedWalls
{
fixedWalls
type fixedValue;
value uniform (0 0 0);
}
frontAndBack
{ frontAndBack
type empty;
type empty;
}
}
fixedWalls
type fixedValue;
value uniform (0 0 0);
712
Boundary conditions and initial conditions
The 0/p dictionary
• For a generic case, the numerical type BC are assigned as follows (p),
boundaryField frontAndBack
{ type empty;
type zeroGradient;
movingWall
{
type zeroGradient;
}
type zeroGradient;
fixedWalls
fixedWalls
{
type zeroGradient; fixedWalls
}
frontAndBack
{
type empty;
} frontAndBack
}
type empty;
fixedWalls
type zeroGradient;
713
Roadmap
714
Numerical playground
Merry-go-round:
Pure convection of a passive scalar in a vector
field – One dimensional tube.
715
Numerical playground
• This is a visual and mental exercise only.
$PTOFC/101FVM/pureConvection/orthogonal_1d
• In this directory, you will also find the README.FIRST file with the
instructions of how to run the case.
716
Numerical playground
Pure convection of a scalar in a vector field – One dimensional tube.
U = zeroGradient
T = zeroGradient
U = (1 0 0) U = zeroGradient
T=1 T = zeroGradient
(0 0 0) (1 0 0)
U = zeroGradient
T = zeroGradient
Initial conditions
U = (1 0 0)
T=0
717
Numerical playground
• This problem has an exact solution in the form of a traveling wave.
• We will use this case to study the different discretization schemes implemented in
OpenFOAM®.
• In the figure, we show the solution for time = 0.5 s
www.wolfdynamics.com/wiki/pureconvection/xani1.gif
www.wolfdynamics.com/wiki/pureconvection/xani2.gif
718
Numerical playground
Comparison of different spatial discretization schemes. Comparison of different spatial discretization schemes.
Euler in time – 100 cells – CFL = 0.1 Euler in time – 100 cells – CFL = 0.1
Linear limiter functions on the Sweby diagram. Non-linear limiter functions on the Sweby diagram.
719
Numerical playground
Comparison of different gradient limiters. Comparison of different gradient limiters.
Linear upwind in space – Euler in time – 100 cells – Linear upwind in space – Euler in time – 100 cells –
CFL 0.1 CFL 0.1
720
Numerical playground
Comparison of different time discretization schemes Comparison of Crank Nicolson blending factor using
and gradient limiters. cellLimited leastSquares 0.5 gradient limiter.
Linear upwind in space – 100 cells – CFL 0.1 Linear upwind in space – 100 cells – CFL 0.1
721
Numerical playground
Comparison of different time-step size (different CFL Comparison of different mesh sizes.
number). Linear upwind in space – Euler in time
Linear upwind in space – Euler in time – 100 cells
722
Numerical playground
• This case was for your eyes and brain only, but we encourage you to reproduce all the previous
results,
• Use all the time discretization schemes.
• Use all the spatial discretization schemes.
• Use all the gradient discretization schemes.
• Use gradient limiters.
• Use different mesh resolution.
• Use different time-steps.
723
Numerical playground
Exercises
• Which one of the following schemes is useless: upwind, downwind, or linear
• Compare the solution obtained with the following schemes: upwind, linearUpwind, MUSCL, QUICK, cubic,
UMIST, OSHER, Minmod, vanAlbada. Are all of them bounded? Are they second order accurate?
• Use the linearUpwind method with Gauss linear, Gauss pointLinear and leastSquares for gradient
computations, which method is more accurate?
• Imagine that you are using the linearUpwind method with no gradient limiters. How will you stabilize the
solution if it becomes unbounded?
• When using gradient limiters, what is clipping?
• Use the linearUpwind with different gradient limiters. Which method is more unbounded?
• Use the vanLeer method with a CFL number of 0.1, 0.9 and 2, did all solutions converge? Are both solutions
bounded?
• In the directory tri_mesh, you will find the same case setup using a triangular mesh.
• Run the case and compare the solution with the equivalent setup using the orthogonal mesh.
• Repeat the same experiments as before and draw your conclusions about which method is better
for unstructured meshes.
• With unstructured meshes, is it possible to get the same accuracy level as for orthogonal meshes?
724
Numerical playground
Exercises
• The solver scalarTransportFoam does not report the CFL number on the screen. How will you compute
the CFL number in this case?
(Hint: you can take a look at the post-processing slides or the utilities directory)
• Which one is more diffusive, spatial discretization or time discretization?
• Are all time discretization schemes bounded?
• If you are using the Crank-Nicolson scheme, how will you avoid oscillations?
• Does the solution improve if you reduce the time-step?
• Use the upwind scheme and a really fine mesh. Does the accuracy of the solution improve?
• From a numerical point of view, what is the Peclet number? Can it be compared to the Reynolds number?
• If the Peclet number is more than 2, what will happen with your solution if you were using a linear scheme?
(Hint: to change the Peclet number you will need to change the diffusion coefficient)
• Pure convection problems have analytical solutions. You are asked to design your own tutorial with an
analytical solution in 2D or 3D.
• Try to break the solver using a time step less than 0.005 seconds. You are allowed to modify the original mesh
and use any combination of discretization schemes.
725
Numerical playground
Slide:
2D Laplace equation in a square domain.
726
Numerical playground
• This is a visual and mental exercise only.
$PTOFC/101FVM/laplace
• In this directory, you will also find the README.FIRST file with the
instructions of how to run the case.
727
Numerical playground
2D Laplace equation in a square domain
728
Numerical playground
2D Laplace equation in a square domain
• This case consist of one domain and three different element types.
Domain
• We will study the influence of the element type on the gradients computation.
• We will also study the influence of the gradSchemes method and laplacianSchemes
method on the solution.
730
Numerical playground
2D Laplace equation in a square domain
A B gradSchemes:
Gauss linear
laplacianSchemes:
Gauss linear orthogonal
A. Hexahedral mesh
B. Triangular mesh
C. Polyhedral mesh
T field
731
Numerical playground
2D Laplace equation in a square domain
A B gradSchemes:
Gauss linear
laplacianSchemes:
Gauss linear orthogonal
A. Hexahedral mesh
B. Triangular mesh
C. Polyhedral mesh
A B gradSchemes:
Gauss linear
laplacianSchemes:
Gauss linear limited 1
A. Hexahedral mesh
B. Triangular mesh
C. Polyhedral mesh
A B gradSchemes:
Gauss leastSquares
laplacianSchemes:
Gauss linear orthogonal
A. Hexahedral mesh
B. Triangular mesh
C. Polyhedral mesh
A B gradSchemes:
Gauss leastSquares
laplacianSchemes:
Gauss linear limited 1
A. Hexahedral mesh
B. Triangular mesh
C. Polyhedral mesh
736
Numerical playground
Exercises
• Run the case using all gradient discretization schemes available. Which scheme gives the best results?
• According to the previous results, which element type is the best one? Do you think that the choice of the
element type is problem dependent (e.g., direction of the flow)?
• Use the leastSquares method for gradient discretization, and the corrected and uncorrected method for
Laplacian discretization. Do you get the same results in all the meshes? How can you improve the results?
(Hint: look at the corrections)
• Does it make sense to do more non-orthogonal corrections using the uncorrected method?
• Run a case only 1 iteration. Do you get a converged solution? Is there a difference between 1 and 100
iterations? Compare the solutions.
• Use a different interpolation method for the diffusion coefficient. Do you get the same results?
• Try to break the solver (this is a difficult task in this case). You are allowed to modify the original mesh and
use any combination of discretization schemes.
737
Numerical playground
Swing:
Flow in a lid-driven square cavity – Re = 100
Effect of grading and non-orthogonality on the
accuracy of the solution
738
Numerical playground
Flow in a lid-driven square cavity – Re = 100
Non-orthogonal mesh vs. orthogonal mesh
• And as CFD is not only about pretty colors, we should also validate
the results
X centerline
High-Re Solutions for incompressible flow using the navier-stokes equations and a multigrid method
U. Ghia, K. N. Ghia, C. T. Shin.
Journal of computational physics, 48, 387-411 (1982) 740
Numerical playground
LaplacianSchemes orthogonal – Non-orthogonal corrections enabled
Y centerline
• And as CFD is not only about pretty colors, we should also validate
the results
X centerline
High-Re Solutions for incompressible flow using the navier-stokes equations and a multigrid method
U. Ghia, K. N. Ghia, C. T. Shin.
Journal of computational physics, 48, 387-411 (1982) 741
Numerical playground
How to adjust the numerical method to deal with non-orthogonality
ddtSchemes • In the dictionary fvSchemes we can enable non-
{
default backward; orthogonal corrections.
}
• Non-orthogonal corrections are chosen using the
gradSchemes
{ keywords laplacianSchemes and snGradSchemes.
default Gauss linear;
//default Gauss skewCorrected linear; • These are the laplacianSchemes and
//default cellMDLimited Gauss linear 1;
grad(p) Gauss linear; snGradSchemes schemes that you will use most of the
}
times:
divSchemes
{ • orthogonal: second order accurate, bounded on
default
//div(phi,U)
none;
Gauss linearUpwind default;
perfect meshes, without non-orthogonal
div(phi,U) Gauss linear; corrections.
}
• corrected: second order accurate, bounded
laplacianSchemes
{ depending on the quality of the mesh, with non-
default
//default
Gauss linear orthogonal;
Gauss linear limited 1;
orthogonal corrections.
//default Gauss skewCorrected linear limited 1;
} • limited : second order accurate, bounded
interpolationSchemes
depending on the quality of the mesh, with non-
{ orthogonal corrections.
//default skewCorrected linear;
default linear; • uncorrected: second order accurate, without
}
non-orthogonal corrections. Stable but more
snGradSchemes
{
diffusive than limited and corrected.
default orthogonal;
//default limited 1;
}
742
Numerical playground
How to adjust the numerical method to deal with non-orthogonality
solvers • Additionally, in the dictionary fvSolution we need to
{
p define the number of PISO corrections (nCorrectors) and
{ non-orthogonal corrections (nNonOrthogonalCorrectors).
solver PCG;
preconditioner DIC;
tolerance 1e-06;
• You need to do at least one PISO correction. Increasing the
relTol 0; number of PISO correctors will improve the stability and
}
accuracy of the solution at a higher computational cost.
pFinal
{ • For orthogonal meshes, 1 PISO correction is ok. But as
$p;
relTol 0; most of the time you will deal with non-orthogonal meshes,
} doing 2 PISO corrections is a good choice.
U
{ • If you are using a method with non-orthogonal corrections
solver
smoother
smoothSolver;
symGaussSeidel;
(corrected or limited 1-0.5), you need to define the number
tolerance 1e-08; of non-orthogonal corrections (nNonOrthogonalCorrectors).
relTol 0;
}
}
• If you use 0 nNonOrthogonalCorrectors, you are
computing the initial approximation using central differences
PISO
{ (accurate but unstable), with no explicit correction.
nCorrectors 1;
nNonOrthogonalCorrectors 0; • To take into account the non-orthogonality of the mesh, you
pRefCell 0;
pRefValue 0; will need to increase the number of corrections (you get
} better approximations using the previous correction).
• Usually 2 nNonOrthogonalCorrectors is ok.
743
Numerical playground
• We will now illustrate a few of the discretization schemes available in OpenFOAM®
using a model case.
• We will use the lid-driven square cavity case to study the effect of grading and non-
orthogonality on the accuracy of the solution
• This case is located in the directory:
$PTOFC/101FVM/nonorthoCavity/
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
744
Numerical playground
What are we going to do?
• This is the same case as the one we used during the first tutorial session.
• The only difference is that we have modified the mesh a little bit in order to add grading and non-orthogonality.
• After generating the mesh, we will use the utility checkMesh to control the quality of the mesh. Is it a good
mesh?
• We will use this case to learn how to adjust the numerical schemes according to mesh non-orthogonality and
grading.
• After finding the numerical solution we will do some sampling and plotting.
1. $> foamCleanTutorials
2. $> blockMesh –dict system/blockMeshDict.0
3. $> checkMesh
4. $> pisoFoam | log.solver
5. $> postProcess -func sampleDict -latestTime
6. $> gnuplot gnuplot/gnuplot_script
7. $> paraFoam
745
Numerical playground
To run the case, follow these steps
• First run the case using the original dictionaries. Did it crash right?
• Now change the laplacianSchemes and snGradSchemes to limited 1. It crashed again but
this time it ran a few more time-steps, right?
• Now increase the number of nNonOrthogonalCorrectors to 2. It crashed again but it is running
more time-steps, right?
• Now increase the number of PISO corrections to 2 (nCorrectors). Did it run?
• Basically we enabled non-orthogonal corrections, we computed better approximations of the
gradients, and we increased the number of PISO corrections to get better predictions of the field
variables (U and p).
• Now set the number of nNonOrthogonalCorrectors to 0. Did it crash right? This is telling us
that the mesh is sensitive to the gradients.
• Now change the laplacianSchemes and snGradSchemes to limited 0 (uncorrected). In this
case we are not using non-orthogonal corrections, therefore there is no need to increase the
value of nNonOrthogonalCorrectors.
• We are using a method that uses a wider stencil to compute the Laplacian, this method is more
stable but a little bit more diffusive. Did it run?
• At this point, compare the solution obtained with corrected and uncorrected schemes. Which
one is more diffusive?
746
Numerical playground
• When it comes to laplacianSchemes and snGradSchemes this is how we proceed most of
the times (a robust setup),
laplacianSchemes
{
default Gauss linear limited 1; PISO
} {
nCorrectors 2;
snGradSchemes nNonOrthogonalCorrectors 1;
{ }
default limited 1;
}
• This method works fine for meshes with non-orthogonality less than 75.
• If the non-orthogonality is more than 75, you should consider using limited 0.5, and increasing
nCorrectors and nNonOrthogonalCorrectors.
• When the non-orthogonality is more than 85, the best solution is to redo the mesh.
747
Numerical playground
Exercises
• Using the non-orthogonal mesh and the original dictionaries, try to run the solver reducing the time-step. Do
you get a solution at all?
• Try to get a solution using the method limited 1 and two nNonOrthogonalCorrectors (leave nCorrectors
equal to 1).
(Hint: try to reduce the time-step)
• If you managed to get a solution using the previous numerical scheme. How long did it take to get the
solution? Use the robust setup, clock the time and compare with the previous case. Which one is faster? Do
you get the same solution?
• Instead of using the non-orthogonal mesh, use a mesh with grading toward all edges. How will you stabilize
the solution?
(Hint: take a look at the blockMesh slides in order to add grading to the mesh)
• Try to get a solution using a time-step of 0.05 seconds. Use the original discretization schemes for the gradient
and convective terms.
(Hint: increase nCorrectors and nNonOrthogonalCorrectors)
• Using the uniform orthogonal mesh and a robust numerics, determined the largest CFL you can use. Is the
solution still accurate? What about the clock-speed?
• Try to break the solver and interpret the output screen. You are allowed to modify the original mesh and use
any combination of discretization schemes.
748
Numerical playground
Seesaw:
Sod’s shock tube.
749
Numerical playground
Sod’s shock tube
• This case has an analytical solution and plenty of experimental data.
• This is an extreme test case used to test solvers.
• Every single commercial and open source solver use this case for validation of the numerical
schemes.
• The governing equation of this test case are the Euler equations.
750
Numerical playground
High Purity Photolysis Shock Tube (NASA Tube)
Shock tube. The driver section, including vacuum pumps, controls, and helium driver gas.
Photo credit: Stanford University. http://hanson.stanford.edu/index.php?loc=facilities_nasa
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose. 751
Numerical playground
Sod’s shock tube
752
Numerical playground
Sod’s shock tube
$PTOFC/101FVM/shockTube/
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
754
Numerical playground
What are we going to do?
• Now is your turn.
• You are asked to select the best discretization scheme for the physics involve.
• Remember the following concepts: accuracy, stability and boundedness.
• We will compare your numerical solution with the analytical solution.
• At this point, we are very familiar with the numerical schemes. It is up to you to choose the best
setup.
• You can start using the original dictionaries.
• To find the numerical solution we will use the solver rhoPimpleFoam.
• rhoPimpleFoam is a transient solver for laminar or turbulent flow of a compressible gas.
• After finding the numerical solution we will do some sampling.
• At the end, we will do some plotting (using gnuplot or Python) and scientific visualization.
755
Numerical playground
Running the case
• You will find this tutorial in the directory $PTOFC/101FVM/schockTube
• In the terminal window type:
1. $> foamCleanTutorials
2. $> blockMesh
3. $> checkMesh
4. $> rm –rf 0
5. $> cp –r 0_org 0
6. $> setFields
7. $> rhoPimpleFoam | tee log.solver
8. $> postProcess -func sampleDict -latestTime
9. $> paraFoam
• To plot the analytical solution against the numerical solution, go to the directory python and run the Python script.
• In the terminal window type:
• The Python script will save four .png files with the solution. Feel free to explore and adapt the Python script to your needs.
• Python (version 3) must be installed in order to use the script
756
Numerical playground
Running the case
• If you used the values proposed in the dictionaries, the solution diverged, right? Try to get the
case working.
Hint: look at the gradient limiters.
• By adjusting the gradient limiters, the case will run, but the final solution is not very accurate.
How can you increase the accuracy of the solution?
Hint: look at the PIMPLE corrections.
757
Numerical playground
Exercises
• Using the proposed case setup, try to get an accurate solution by reducing the time-step or refining the mesh.
Did you succeed in getting an accurate solution?
• Run the case using different time discretization schemes.
• Run the case using different gradient discretization schemes.
• Run the case using different convective discretization schemes for the term div(phi,U).
• Run the case using different convective discretization schemes for the terms div(phi,e) and div(phi,K). What
are the variables e and K?
• Extend the case to 2D and 3D. Do you get the same solution?
• Try to run a 2D case using a triangular mesh and adjust the numerical scheme to get an accurate and stable
solution.
• Try to run the 1D case using an explicit solver. For the same CFL number, do you have the same time step
size as for the implicit solver?
(Hint: look for the solver with the word Central)
• Try to break the solver (this is extremely easy in this case). You are allowed to modify the original mesh and
use any combination of discretization schemes.
758
Module 7
Highlights – Implementing boundary
conditions and initial conditions using
codeStream
759
Roadmap
1. codeStream – Highlights
2. Implementing boundary conditions using
codeStream
3. Solution initialization using codeStream
760
codeStream – Highlights
codeStream – Boundary conditions
• There are many boundary conditions available in OpenFOAM®.
• But from time to time it may happen that you do not find what you are looking for.
• It is possible to implement your own boundary conditions, so in theory you can do whatever you
want.
• Remember, you have the source code.
• To implement your own boundary conditions, you have three options:
• Use codeStream.
• Use high level programing.
• Use an external library (e.g., swak4foam).
• codeStream is the simplest way to implement boundary conditions, and most of the times you
will be able to code boundary conditions with no problem.
• If you can not implement your boundary conditions using codeStream, you can use high level
programming. However, this requires some knowledge on C++ and OpenFOAM® API.
• Hereafter, we are going to work with codeStream and basic high-level programming.
• We are not going to work with swak4Foam because it is an external library that is not officially
supported by the OpenFOAM® foundation. However, it works very well and is relatively easy to
use. 761
codeStream – Highlights
codeStream – Initial conditions
• When it comes to initial conditions, you can use the utility setFields.
• This utility is very flexible, you can even read STL files and use them to initialize fields.
• But again, it may happen that you can not get the desired results.
• As for boundary conditions, to implement your own initials conditions you have three options:
• Use codeStream.
• Use high level programing.
• Use an external library (e.g., swak4foam).
• codeStream is the simplest way to implement initial conditions, and most of the times you will
be able to code initial conditions with no problem.
• If you can not implement your initial conditions using codeStream, you can use high level
programming. However, this requires some knowledge on C++ and OpenFOAM® API.
• Hereafter, we are going to work only with codeStream.
• Using high level programming is a little bit trickier, and we guarantee you that 99.9% of the times
codeStream will work.
• We are not going to work with swak4Foam because it is an external library that is not officially
supported by the OpenFOAM® foundation. However, it works very well and is relatively easy to
use. 762
codeStream – Highlights
• Hereafter we will work with codeStream, which will let us program directly in the input
dictionaries.
• With codeStream, we will implement our own boundary conditions and initial conditions without
going thru the hustle and bustle of high-level programming.
• If you are interested in high level programming, refer to the supplements.
• In the supplemental slides, we address the following topics:
• Building blocks, implementing boundary conditions using high level programming,
modifying applications, implementing an application from scratch, and adding the
scalar transport equation to icoFoam.
• High level programming requires some knowledge on C++ and OpenFOAM® API library.
• This is the hard part of programming in OpenFOAM®.
• Before doing high level programming, we highly recommend you try with codeStream, most of
the time it will work.
• Also, before modifying solvers or trying to implement your own solvers, understand the theory
behind the FVM.
• Remember, you can access the API documentation in the following link,
https://cpp.openfoam.org/v8
763
Roadmap
1. codeStream – Highlights
2. Implementing boundary conditions using
codeStream
3. Solution initialization using codeStream
764
Implementing boundary conditions using codeStream
• OpenFOAM® includes the capability to compile, load and execute C++ code at run-time.
• This capability is supported via the directive #codeStream, that can be used in any input file for
run-time compilation.
• This directive reads the entries code (compulsory), codeInclude (optional), codeOptions
(optional), and codeLibs (optional), and uses them to generate the dynamic code.
• The source code and binaries are automatically generated and copied in the directory
dynamicCode of the current case.
• The source code is compiled automatically at run-time.
• The use of codeStream is a very good alternative to avoid high level programming of boundary
conditions or the use of external libraries.
• Hereafter we will use codeStream to implement new boundary conditions.
• Have in mind that codeStream can be used in any dictionary.
765
Implementing boundary conditions using codeStream
Body of the codeStream directive for boundary conditions
patch-name Patch name
{
type fixedValue;
value #codeStream
Use codeStream to set the value
{ of the boundary condition
codeInclude
#{
#include "fvCFD.H" Files needed for compilation
#};
codeOptions
#{
-I$(LIB_SRC)/finiteVolume/lnInclude \ Compilation options
-I$(LIB_SRC)/meshTools/lnInclude
#};
code
#{ Insert your code here.
At this point, you need to know
#}; how to access mesh information
};
}
766
Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codeStream
• Let us implement a parabolic inlet profile.
• The firs step is identifying the patch, its location and the dimensions.
• You can use paraview to get all visual references.
Outlet
pressure-outlet-7
Inlet
velocity-inlet-5
Inlet
velocity-inlet-6 Bounds of velocity-inlet-5 boundary patch
Parabolic inlet profile 767
Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codeStream
• We will use the following formula to implement the parabolic inlet profile
• For this specific case c is the patch midpoint in the y direction (8), r is the patch semi-height or
radius (8) and Umax is the maximum velocity.
• We should get a parabolic profile similar to this one,
768
Implementing boundary conditions using codeStream
• The codeStream BC in the body of the file U is as follows,
code
#{ Insert your code here.
At this point, you need to know
#}; how to access mesh information
};
}
769
Implementing boundary conditions using codeStream
• The code section of the codeStream BC in the body of the file U is as follows,
• Lines 3-11, are always standard, they are used to access boundary mesh information.
• In lines 3-6 we access the current dictionary.
• In line 8 we access the mesh database.
• In line 9 we get the label id (an integer) of the patch velocity-inlet-5 (notice that you need to give the name of
the patch).
• In line 10 using the label id of the patch, we access the boundary mesh information.
• In line 12 we initialize the vector field. The statement patch.size() gets the number of faces in the patch, and
the statement vector(0, 0, 0) initializes a zero-vector field in the patch. 770
Implementing boundary conditions using codeStream
• The code section of the codeStream BC in the body of the file U is as follows,
1. $> foamCleanTutorials
2. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh
3 $> checkMesh
4. $> rm –rf 0
5. $> cp –r 0_org 0
6. $> pisoFoam | tee log.solver
7. $> paraFoam
773
Implementing boundary conditions using codeStream
codeStream works with scalar and vector fields
• We just implemented the input parabolic profile using a vector field.
• You can do the same using a scalar field, just proceed in a similar way.
• Remember, now we need to use scalars instead of vectors.
• And you will also use an input dictionary holding a scalar field.
1 code
2 #{
3 ...
4 ...
5 ...
6 scalarField S(patch.size(), scalar(0) ); Initialize scalar field
7
8 forAll(S, i) Loop using scalar field size
9 {
10 const scalar y = patch.Cf()[i][1];
11 S[i] = scalar( 2.0*sin(3.14159*y/8.) );
Write profile values
12 } in scalar field
13
14 writeEntry(os, "", S);
Write output to input
15 #}; dictionary
Notice that the name of the field does not need to be the same as the name of the input dictionary
774
Implementing boundary conditions using codeStream
Implementation of a paraboloid inlet profile using codeStream
• Let us work in a case a little bit more complicated, a paraboloid input profile.
• As usual, the first step is to get all the spatial references.
Inlet
auto3
776
Implementing boundary conditions using codeStream
• The codeStream BC in the body of the file U is as follows,
codeLibs
#{
-lmeshTools \
-lfiniteVolume
#};
Insert your code here.
code
#{
We will implement the following
equation
#};
};
}
777
Implementing boundary conditions using codeStream
• Hereafter, we only show the actual implementation of the codeStream boundary condition.
• The rest of the body is a template that you can always reuse. Including the section of how to
access the dictionary and mesh information.
• Remember, is you are working with a vector, you need to use vector fields. Whereas, if you are
working with scalars, you need to use scalars fields.
1 code
2 #{
3 ...
4 ...
5 ...
6 vectorField U(patch.size(), vector(0, 0, 0) );
7
8 const scalar s = 0.5; Initialize vector field
9
10 forAll(U, i) Initialize scalar
11 {
12 const scalar x = patch.Cf()[i][0];
Access faces center
13 const scalar y = patch.Cf()[i][1];
14 const scalar z = patch.Cf()[i][2]; coordinates (x, y, and z)
15
16 U[i] = vector(-1.*(pow(z/s, 2) + pow((y-s)/s,2) - 1.0), 0, 0);
17 }
18
19 writeEntry(os, "", U);
20 #};
778
Implementing boundary conditions using codeStream
Implementation of a paraboloid inlet profile using codeStream
• This case is ready to run, the input files are located in the directory
$PTOFC/101programming/codeStream_BC/3Delbow_Uparaboloid/
• To run the case, type in the terminal,
1. $> foamCleanTutorials
2. $> gmshToFoam ../../../meshes_and_geometries/gmsh_elbow3d/geo.msh
780
Implementing boundary conditions using codeStream
codedFixedValue and codedMixed boundary conditions
• OpenFOAM® also includes the boundary conditions codedFixedValue and codedMixed.
• These boundary conditions are derived from codeStream and work in a similar way.
• They use a friendlier notation and let you access more information of the simulation database
(e.g. time).
• The source code and binaries are automatically generated and copied in the directory
dynamicCode of the current case.
• Another feature of these boundary conditions, is that the code section can be read from an
external dictionary (system/codeDict), which is run-time modifiable.
• The boundary condition codedMixed works in similar way. This boundary condition gives you
access to fixed values (Dirichlet BC) and gradients (Neumann BC).
• Let us implement the parabolic profile using codedFixedValue.
781
Implementing boundary conditions using codeStream
Body of the codedFixedValue boundary conditions
patch-name Patch name
{
type codedFixedValue; Use codedFixedValue and
value uniform (0 0 0); initializations
Unique name of the new boundary
name name_of_BC; condition.
If you have more codedFixedValue
/* BC, the names must be different
codeOptions
#{
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude Optional compilation options.
#}; You do not need to add these options
unless it is required.
codeInclude At the following link, you can find a bug
#{ related to codedFixedValue (SEP2020)
#include "fvCFD.H" https://bugs.openfoam.org/view.php?id=3555
#include <cmath>
#include <iostream>
#};
In this section we do the actual
*/
implementation of the boundary
code condition.
#{ This is the only part of the body
that you will need to change. The
#}; rest of the body is a template that
}
you can always reuse. 782
Implementing boundary conditions using codeStream
• The code section of the codeStream BC in the body of the file U is as follows,
1 code
2 #{
3 const fvPatch& boundaryPatch = patch();
4 const vectorField& Cf = boundaryPatch.Cf();
5 vectorField& field = *this;
6
7 scalar U_0 = 2, p_ctr = 8, p_r = 8;
8
9 forAll(Cf, faceI)
10 {
11 field[faceI] = vector(U_0*(1-(pow(Cf[faceI].y()-p_ctr,2))/(p_r*p_r)),0,0);
12 }
13 #};
• Lines 3-5, are always standard, they give us access to mesh and field information in the patch.
• The coordinates of the faces center are stored in the vector field Cf (line 4).
• In this case, as we are going to implement a vector profile, we initialize a vector field where we are going to
assign the profile (line 5).
• In line 7 we initialize a few constants that will be used in our implementation.
• In lines 9-12 we use a forAll loop to access the boundary patch face centers and to assign the velocity profile
values.
• In line 11 we do the actual implementation of the boundary profile (similar to the codeStream case). The
vector field was initialized in line 5.
783
Implementing boundary conditions using codeStream
codedFixedValue and codedMixed boundary conditions
• As you can see, the syntax and use of the codedFixedValue and codedMixed boundary
conditions is much simpler than codeStream.
• You can use these instructions as a template.
• At the end of the day, you only need to modify the code section.
• Depending of what you want to do, you might need to add new headers and compilation options.
• Remember, is you are working with a vector, you need to use vector fields. Whereas, if you are
working with scalars, you need to use scalars fields.
• One disadvantage of these boundary conditions, is that you can not visualize the fields at time
zero. You will need to run the simulation for at least one iteration.
• On the positive side, accessing time and other values from the simulation database is
straightforward.
• Time can be accessed by adding the following statement,
this->db().time().value()
784
Implementing boundary conditions using codeStream
• Let us add time dependency to the parabolic profile.
1 code
2 #{
3 const fvPatch& boundaryPatch = patch();
4 const vectorField& Cf = boundaryPatch.Cf();
5 vectorField& field = *this;
6
7 scalar U_0 = 2, p_ctr = 8, p_r = 8;
8
9 scalar t = this->db().time().value(); Time
10
11 forAll(Cf, faceI)
12 {
13 field[faceI] = vector(sin(t)*U_0*(1-(pow(Cf[faceI].y()-p_ctr,2))/(p_r*p_r))),0,0);
14 }
15 #};
Time dependency
• This implementation is similar to the previous one, we will only address how to deal with time.
• In line 8 we access simulation time.
• In line 13 we do the actual implementation of the boundary profile (similar to the codeStream
case). The vector field was initialized in line 5 and time is accessed in line 9.
• In this case, we added time dependency by simple multiplying the parabolic profile by the
function sin(t).
785
Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codedFixedValue
• This case is ready to run, the input files are located in the directory
$PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet_timeDep
• To run the case, type in the terminal,
1. $> foamCleanTutorials
2. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh
786
Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codedFixedValue
• If everything went fine, you should get something like this,
www.wolfdynamics.com/wiki/BCIC/elbow_unsBC1.gif
787
Implementing boundary conditions using codeStream
Filling a tank using codedFixedValue
• Let us do a final example.
Water enters here
• We will deal with scalar and vector fields at the same This is a face selection in a single boundary patch
time.
• We will use codedFixedValue.
• For simplicity, we will only show the code section of the
input files.
• Remember, the rest of the body can be used as a
template.
• And depending of what you want to do, you might need
to add new headers, libraries, and compilation options.
• Hereafter we will setup an inlet boundary condition in a
portion of an existing patch.
• By using codedFixedValue BC, we do not need to
modify the actual mesh topology.
• We will assign a velocity field and a scalar field to a set
of faces (dark area in the figure).
• We are going to simulate filling a tank with water.
• We will use the solver interFoam. The tank is initially empty
788
Implementing boundary conditions using codeStream
• Definition of the vector field boundary condition (dictionary file U),
789
Implementing boundary conditions using codeStream
• Definition of the vector field boundary condition (dictionary file U),
7 code Code section. The actual implementation of the BC is done in this section
8 #{
...
... Loop using size of boundary patch (Cf) and iterator
... faceI.
19 This is equivalent to:
20 forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++)
21 {
22
23 if (
24 (Cf[faceI].z() > minz) &&
Use conditional structure to
25 (Cf[faceI].z() < maxz) &&
26 (Cf[faceI].y() > miny) && select faces according to the
27 (Cf[faceI].y() < maxy) variables defined in lines 13-16
28 )
29 {
30 if ( t < 1.)
31 { Use conditional structure to
32 field[faceI] = vector(1,0,0); add time dependency and
33 } assign values to the
34 else
selected faces.
35 {
36 field[faceI] = vector(0,0,0); The variable field was
37 } initialize in line 11.
38 }
39 }
40 #};
41 }
790
Implementing boundary conditions using codeStream
• Definition of the scalar field boundary condition (dictionary file alpha.water),
7 code Code section. The actual implementation of the BC is done in this section
8 #{
...
Loop using size of boundary patch (Cf) and iterator
...
... faceI.
22 This is equivalent to:
23 forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++)
24 {
25 if (
26 (Cf[faceI].z() > minz) && Use conditional structure to
27 (Cf[faceI].z() < maxz) && select faces according to the
28 (Cf[faceI].y() > miny) &&
variables defined in lines 13-16
29 (Cf[faceI].y() < maxy)
30 )
31 {
32 if ( t < 1.)
33 { Use conditional structure to add
34 field[faceI] = 1.; time dependency and assign
35 }
36 else
values to the selected faces.
37 { The variable field was initialize in
38 field[faceI] = 0.; line 11.
39 }
40 }
41 }
42 #};
43 }
792
Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codedFixedValue
• This case is ready to run, the input files are located in the directory
$PTOFC/101programming/codeStream_BC/fillBox_BC/
• To run the case, type in the terminal,
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0
4. $> cp –r 0_org 0
5. $> decomposePar
6. $> mpirun -np 4 interFoam -parallel | tee log.solver
7. $> reconstructPar
8. $> paraFoam
00
00
00
0 02
0 01
0
0 02 0 0 0 1 12 1 1 1 2
1. codeStream – Highlights
2. Implementing boundary conditions using
codeStream
3. Solution initialization using codeStream
795
Solution initialization using codeStream
• When it comes to initial conditions, you can use the utility setFields.
• This utility is very flexible, you can even read STL files and use them to initialize your fields.
• But in case that you can not get the desired results using setFields, you can implement your
own initial conditions using codeStream.
• To implement initial conditions using codeStream, we proceed in a similar way as for boundary
conditions.
• The source code and binaries are automatically generated and copied in the directory
dynamicCode of the current case.
• The source code is compiled automatically at run-time.
• The use of codeStream is a very good alternative to avoid high level programming of initial
conditions or the use of external libraries.
• Hereafter we will use codeStream to implement new initial conditions.
796
Solution initialization using codeStream
Body of the codeStream directive for initial conditions
internalField #codeStream Use codeStream to set the value
{ of the initial conditions
{
codeInclude
#{
#include "fvCFD.H" Files needed for compilation
Initial conditions
#};
codeOptions
#{
-I$(LIB_SRC)/finiteVolume/lnInclude \ Compilation options
-I$(LIB_SRC)/meshTools/lnInclude
#};
codeLibs
Libraries needed for compilation.
#{
-lmeshTools \ Needed if you want to visualize the
-lfiniteVolume output of the initial conditions at
#}; time zero
code
#{
Insert your code here.
#}; At this point, you need to know
}; how to access internal mesh
} information
797
Solution initialization using codeStream
Implementation of an elliptic initialization using codeStream
• Let us implement an elliptic initialization using codeStream.
• The firs step is to know your domain and identify the region that you want to initialize.
• Then you will need to do a little bit of math to get the expression for the initialization.
• In this example, we are also going to show you how to do the same initialization by reading a
STL file with the utility setFields.
Phase 1
798
Solution initialization using codeStream
• The codeStream IC in the body of the file alpha.phase1 is as follows,
code
#{
Insert your code here.
#}; At this point, you need to know
}; how to access internal mesh
} information
799
Solution initialization using codeStream
• The code section of the codeStream IC in the body of the file alpha.phase1 is as follows,
following statement
}
800
Solution initialization using codeStream
Implementation of an elliptic initialization using codeStream
• This case is ready to run, the input files are located in the directory
$PTOFC/101programming/codeStream_INIT/elliptical_IC
• To run the case, type in the terminal,
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0
4. $> cp –r 0_org 0
5. $> paraFoam
6. $> interFoam | tee log.solver
7. $> paraFoam
801
Solution initialization using codeStream
Implementation of an elliptic initialization using codeStream
Surface tension driven flow - Bubble in a zero gravity flow using interFoam
802
Solution initialization using codeStream
Elliptic initialization using setFields
• Let us do the same initialization using a STL file with setFields.
• First, you will need to create the solid model that encloses the region you want to initialize.
• For this, you can use your favorite CAD/solid modeling software. Remember to save the
geometry is STL format.
• Then you will need to read in the STL file using setFields.
• You will need to modify the setFieldsDict dictionary.
Region defined by
the STL file
Computational domain
803
Solution initialization using codeStream
The setFieldsDict dictionary
defaultFieldValues
(
volScalarFieldValue alpha.phase1 0 Initialize the whole domain to zero
);
regions
setFields method to read STL files.
( If you want to know all the options
available use a word that does not exist
surfaceToCell in the enumerator list (e.g. banana)
{
file "./geo/ellipse.stl"; Location of the STL file to read
outsidePoints ((0.5 0.85 0)); A point located outside the STL
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0
4. $> cp –r 0_org 0
5. $> setFields
6. $> paraFoam
805
Solution initialization using codeStream
Rayleigh-Taylor instability initialization
806
Solution initialization using codeStream
• The code section of the codeStream IC in the body of the file alpha.phase1 is as follows,
{
const scalar x = mesh.C()[i][0];
const scalar y = mesh.C()[i][1];
Access cell centers coordinates
if (y >= -0.05*cos(2*constant::mathematical::pi*x))
{
alpha[i] = 1.;
}
}
807
Solution initialization using codeStream
Rayleigh-Taylor instability initialization
• This case is ready to run, the input files are located in the directory
$PTOFC/101programming/codeStream_INIT/rayleigh_taylor
• To run the case, type in the terminal,
1. $> foamCleanTutorials
2. $> blockMesh
3. $> rm –rf 0
4. $> cp –r 0_org 0
5. $> interFoam | tee log.solver
6. $> paraFoam
808
Solution initialization using codeStream
Rayleigh-Taylor instability initialization
• If everything went fine, you should get something like this,
809
Solution initialization using codeStream
Filling a tank using codeStream and codedFixedValue
• Let us do a final example.
• We will implement BCs and ICs at the same.
• For simplicity, we will only show the code section of the input files.
• This setup is similar to the last example of the previous section (filling a tank using
codedFixedValue).
810
Solution initialization using codeStream
• The code section of the codeStream IC in the body of the file alpha.water is as follows,
internalField #codeStream
Use codeStream to set the
{ value of the initial conditions
if (y <= 0.2)
{ Assign value to alpha according to
alpha[i] = 1.; conditional structure
}
}
811
Solution initialization using codeStream
• The code section of the codeFixedValue BC in the body of the file U is as follows,
812
Solution initialization using codeStream
• The code section of the codeFixedValue BC in the body of the file U is as follows,
if (
(Cf[faceI].z() > min) &&
(Cf[faceI].z() < max) && Use conditional structure to
(Cf[faceI].y() > min) && select faces.
(Cf[faceI].y() < max)
)
{
if ( t < 2.)
{
field[faceI] = vector(1,0,0); Use conditional structure to
} add time dependency and
else
assign values to the
{
field[faceI] = vector(0,0,0); selected faces.
}
}
}
#};
813
Solution initialization using codeStream
• The code section of the codeFixedValue BC in the body of the file alpha.water is as follows,
field = patchInternalField(); Assign value from the internal field to the patch
815
Solution initialization using codeStream
Filling a tank using codeStream and codedFixedValue
• If everything went fine, you should get something like this,
02
02
02
0 22
02
01
0 0 1 1 2 2
816
Module 8
Advanced physics
Turbulence modeling – Multiphase flows –
Compressible flows – Moving bodies –
Source terms – Passive scalars
817
• In this module, we will deal with advanced modeling capabilities.
• Advanced modeling capabilities rely a lot in physical models, such as,
turbulence, multiphase flows, porous media, combustion, radiation, heat
transfer, phase change, acoustics, cavitation, and so on.
• Therefore, it is extremely important to get familiar with the theory behind
these models.
819
A crash introduction to turbulence modeling in OpenFOAM®
What is turbulence?
Wake turbulence behind individual wind turbines Flow visualization over a spinning spheroid
Photo credit: NREL's wind energy research group. Photo credit: Y. Kohama.
Copyright on the images is held by the contributors. Apart from Fair Use, Copyright on the images is held by the contributors. Apart from Fair Use,
permission must be sought for any other purpose. permission must be sought for any other purpose.
Von Karman vortices created when prevailing winds sweeping east across Vortices on a 1/48-scale model of an F/A-18 aircraft inside a Water
the northern Pacific Ocean encountered Alaska's Aleutian Islands Tunnel
Photo credit: USGS EROS Data Center Satellite Systems Branch. Photo credit: NASA Dryden Flow Visualization Facility.
Copyright on the images is held by the contributors. Apart from Fair Use, Copyright on the images is held by the contributors. Apart from Fair Use,
permission must be sought for any other purpose. permission must be sought for any other purpose. 821
A crash introduction to turbulence modeling in OpenFOAM®
Abstract representation of
the drag decomposition
Flow around two spheres. Left image: smooth sphere. Right image: sphere with rough surface at the nose
Photo credit: http://www.mhhe.com/engcs/civil/finnemore/graphics/photos/AuthorRecommendedImages/index.html
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose 822
A crash introduction to turbulence modeling in OpenFOAM®
823
A crash introduction to turbulence modeling in OpenFOAM®
URANS (K-Omega SST with no wall functions) – LES (Smagorinsky) – Vortices visualized by Q-criterion
Vortices visualized by Q-criterion www.wolfdynamics.com/wiki/squarecil/les.gif
www.wolfdynamics.com/wiki/squarecil/urans2.gif
References:
Lyn, D.A. and Rodi, W., The flapping shear layer formed by flow separation from the forward corner of a square cylinder. J. Fluid Mech., 267, 353, 1994.
Lyn, D.A., Einav, S., Rodi, W. and Park, J.H., A laser-Doppler velocimetry study of ensemble-averaged characteristics of the turbulent near wake of a square
cylinder. Report. SFB 210 /E/100.
825
A crash introduction to turbulence modeling in OpenFOAM®
Inflow
Turbulence model 1
Turbulence model 2
Turbulence model 3
Turbulence model 4
Turbulence model 5
Experimental results
Turbulence model 1
Turbulence model 2
Turbulence model 3
Turbulence model 4
Turbulence model 5
Experimental results
• CFD has been around since the late 1970s, and after all these years is not that easy to compute the flow around 2D airfoils.
• In particular, predicting the maximum lift and stall characteristics is not trivial.
References:
F. Menter. “A New Generalized k-omega model. Putting flexibility into Turbulence models (GEKO)”, Ansys Germany
A. J. Wadcock. “Investigation of Low-Speed Turbulent Separated Flow Around Airfoils”, NASA Contractor Report 177450 826
A crash introduction to turbulence modeling in OpenFOAM®
Turbulence modeling in engineering
• Most natural and engineering flows are turbulent, hence the necessity of modeling turbulence.
• The goal of turbulence modeling is to develop equations that predict the time averaged velocity, pressure,
temperature fields without calculating the complete turbulent flow pattern as a function of time.
• There is no universal turbulence model, hence you need to know the capabilities and limitations of the
turbulence models.
• Simulating turbulent flows in any general CFD solver requires selecting a turbulence model, providing initial
conditions and boundary conditions for the closure equations of the turbulent model, selecting a near-wall
modeling, and choosing runtime parameters and numerics.
827
A crash introduction to turbulence modeling in OpenFOAM®
Convective effects
where
Viscous effects
Buoyancy effects
Momentum diffusivity
• Notice that other factors such as free-stream turbulence, surface conditions, blowing, suction,
roughness and other disturbances, may cause transition to turbulence at lower Reynolds
number.
• If you are dealing with natural convection and buoyancy, turbulent flows occurs when
829
A crash introduction to turbulence modeling in OpenFOAM®
Drag coefficient as a function of Reynolds number for Strouhal number for a smooth cylinder [2]
a smooth cylinder [1]
References:
1. Fox, Robert W., et al. Introduction to Fluid Mechanics. Hoboken, NJ, Wiley, 2010
2. Sumer, B. Mutlu, et al. Hydrodynamics Around Cylindrical Structures. Singapore, World Scientic, 2006
831
A crash introduction to turbulence modeling in OpenFOAM®
• The Reynold number in this case is 100, for these conditions the flow still is laminar.
• We are in the presence of the Von Karman vortex street, which is the periodic shedding of vortices caused by
the unsteady separation of the fluid around blunt bodies.
• Vorticity is not a direct indication of turbulence.
• However turbulent flows are rotational, they exhibit vortical structures. 832
A crash introduction to turbulence modeling in OpenFOAM®
In RANS
• The overbar denotes the mean value.
• The prime denotes the fluctuating value.
In LES
• The overbar denotes the filtered value.
• The prime denotes the modeled value or
residual.
• We have defined turbulence as an unsteady, aperiodic motion in which velocity components and every
transported quantity fluctuate in space and time.
• For most engineering application it is impractical to account for all these instantaneous fluctuations.
• Therefore, we need to somehow remove those small scales by using models.
• To remove of filter the instantaneous fluctuations or small scales, two methods can be used: Reynolds
averaging and Filtering
• Both methods introduce additional terms that must be modeled for closure.
• We are going to talk about closure methods later. 833
A crash introduction to turbulence modeling in OpenFOAM®
Laminar flow profile Averaged turbulent flow profile Instantaneous turbulent flow profile
• In the laminar flow case, the velocity gradients close to the walls are low and the velocity profile is parabolic.
• Turbulence has a direct effect on the velocity profiles and mixing of transported quantities.
• The turbulent case shows two regions. One thin region close to the walls with very large velocity gradients,
and a region far from the wall where the velocity profile is nearly uniform.
• The thin region close to the walls is laminar.
• Far from the flows, the flow becomes turbulent.
834
A crash introduction to turbulence modeling in OpenFOAM®
• Turbulence has a direct effect on the velocity profiles and mixing of transported quantities.
• Case (a) correspond to a laminar flow, where the dye can mix with the main flow only via molecular diffusion,
this kind of mixing can take very long times.
• Case (b) shows a transitional state where the dye streak becomes wavy, but the main flow still is laminar.
• Case (c) shows the turbulent state, where the dye streak changes direction erratically, and the dye has mixed
significantly with the main flow due to the velocity fluctuations. 835
A crash introduction to turbulence modeling in OpenFOAM®
uffer layer
iscous sublayer
Critical lengt
integral scales
inertial scales
dissipation scales
• The use of the non-dimensional velocity u+ and non-dimensional distance from the wall y+, results in a
predictable boundary layer profile for a wide range of flows.
• Turbulence models require different considerations depending on whether you solve the viscous sublayer of
model the log-law layer. 837
A crash introduction to turbulence modeling in OpenFOAM®
Buffer layer
Viscous sublayer
Logarithmic layer (log-law)
Note 1: the range of y+ values might change from reference to reference but roughly speaking
they are all close to these values.
Note 2: the y+ upper limit of the buffer layer depends on the Reynolds number. Large Re will
have higher y+ upper limit 839
A crash introduction to turbulence modeling in OpenFOAM®
y+ insensitive
• You can also use the y+ insensitive wall treatment (sometimes known as continuous wall functions or scalable wall functions).
• This near-wall treatment is valid in the whole boundary layer.
• In terms of y+, you can use this approach for values between 1 < y+ < 300.
• This approach is very flexible as it is independent of the y+ value but is not available in all turbulence models.
• You should also be aware of its limitations. 840
A crash introduction to turbulence modeling in OpenFOAM®
Turbulence modeling – Grid scales
Cell size
This cell is resolving the eddies
• Turbulence modelling aims at predicting velocity and transported quantities fluctuations without
calculating the complete turbulent flow pattern as a function of time.
• Everything below grid scales or sub-grid scales (SGS) is modelled or filtered.
• Therefore, if we want to capture all scales we need very fine meshes in the whole domain.
MODELING APPROACH
URANS
Unsteady Reynolds-Averaged Navier-Stokes equations
complexity
• Many more acronyms that fit between RANS/URANS
and SRS.
• Some of the acronyms are used only to differentiate
approaches used in commercial solvers.
PANS, SAS, RSM, EARSM, PITM, SBES, ELES
Scale-Resolving Simulations
DES
SRS
LES
Large Eddy Simulations
DNS
Direct Numerical Simulations
842
A crash introduction to turbulence modeling in OpenFOAM®
Robust. Widely used despite the known limitations of the model. Performs poorly for complex
Standard k–epsilon flows involving severe pressure gradient, separation, strong streamline curvature. Suitable for
initial iterations, initial screening of alternative designs, and parametric studies.
Suitable for complex shear flows involving rapid strain, moderate swirl, vortices, and locally
transitional flows (e.g. boundary layer separation, massive separation, and vortex shedding
Realizable k–epsilon behind bluff bodies, stall in wide-angle diffusers, room ventilation). It overcome the limitations of
the standard k-epsilon model.
Superior performance for wall-bounded boundary layer, free shear, and low Reynolds number
Standard k–omega flows compared to models from the k-epsilon family. Suitable for complex boundary layer flows
under adverse pressure gradient and separation (external aerodynamics and turbomachinery).
Offers similar benefits as standard k–omega. Not overly sensitive to inlet boundary conditions
SST k–omega like the standard k–omega. Provides more accurate prediction of flow separation than other
RANS models. Probably the most widely used RANS model.
844
A crash introduction to turbulence modeling in OpenFOAM®
Turbulence modeling – Starting equations
NSE
If we retain this term, we talk about URANS equations and if we drop it we talk about RANS equations
• The differences are that all quantities have been averaged (the overbar over the primitive variables).
• And the appearance of the Reynolds stress tensor .
• Notice that the Reynolds stress tensor is not actually a stress, it must be multiplied by density in order to have
dimensions corresponding to stresses,
• To derive the RANS equations we used Reynolds decomposition and a few averaging rules (a lot of algebra is
involved),
Reynolds decomposition
846
A crash introduction to turbulence modeling in OpenFOAM®
• The Reynolds stress tensor can be modeled using the Boussinesq hypothesis, Reynolds stress models, non-
linear eddy viscosity models or algebraic models.
• Let us address the Boussinesq hypothesis which is the most widely used approach to model the Reynolds
stress tensor.
• By using this hypothesis we can relate the Reynolds stress tensor to the mean velocity gradient such that,
Effective viscosity
Turbulent viscosity
• Notice that by introducing the Boussinesq approximation the fluctuating quantities (the prime in the equations)
do not appear in the final equations.
• The new equations are expressed entirely n terms of mean values (overbar), which can be computed.
• The problem now reduces to computing the turbulent eddy viscosity in the momentum equation.
• This is done by adding closure models (one-equation, two-equations, algebraic, transition, Reynolds stress,
and so on).
848
A crash introduction to turbulence modeling in OpenFOAM®
Additional remarks
• We just outlined the incompressible RANS.
• The compressible RANS equations are similar, but when we derive them, we use Favre average
(which can be seen as a mass-weighted averaging), instead of Reynolds average.
• Besides RANS, there is also LES and DES turbulence models.
• The idea behind LES/DES models is very similar to RANS, but instead of using averaging we
filter the equations in space, and we solve the temporal scales
• At the end of the day, in LES/DES it is also required to model a stress tensor, usually called the
SGS stress tensor.
• This stress tensor is related to the scales that cannot be resolved with the mesh; therefore, need
to be modelled.
• LES/DES models are intrinsically unsteady and three-dimensional.
• Let us take a look at the governing equations of the RANS model (Wilcox 1998
revision).
• Remember, the main goal of the RANS turbulence models is to model the Reynolds stress
tensor by computing the turbulent eddy viscosity.
849
A crash introduction to turbulence modeling in OpenFOAM®
• These are the closure equations of the turbulence problem using the RANS model.
• These are not physical quantities. They kind of represent the generation and destruction of turbulence.
• In the model, the turbulent eddy viscosity can be computed as follows,
• The model has many closure coefficient that we do not show here. These coefficients are calibrated using
experimental data, DNS simulations, analytical solutions, or empirical data.
• Note that all quantities are computed in function of mean values. The Reynolds stresses are modeled using
the Boussinesq hypothesis. By proceeding in this way, we remove any dependence on the fluctuations.
• It is worth mentioning that different turbulence models will have different ways of computing the turbulent eddy
viscosity. 850
A crash introduction to turbulence modeling in OpenFOAM®
• The initial value for the specific kinetic energy can be computed as follows,
• If you are totally lost, you can use these reference values. They work most of the times, but it is
a good idea to have some experimental data or a better initial estimate.
1 10 100
• By the way, use these guidelines for external aerodynamics only. 851
A crash introduction to turbulence modeling in OpenFOAM®
852
A crash introduction to turbulence modeling in OpenFOAM®
nut(–)WallFunction* or nutUSpaldingWallFunction** or
nut nutUSpaldingWallFunction** nutLowReWallFunction or fixedValue
(with 0 or a small number) (with 0 or a small number)
* $WM_PROJECT_DIR/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions
** For y+ insensitive wall functions (continuous wall functions) 853
A crash introduction to turbulence modeling in OpenFOAM®
855
A crash introduction to turbulence modeling in OpenFOAM®
• To get an initial estimate of the distance from the wall to the first cell center y+, without recurring
to a precursor simulation, you can proceed as follows,
1.
(Skin friction coefficient of a flat plate, there are
2. similar correlations for pipes)
3.
4.
Your desired value
5.
• You will find a simple calculator for the wall distance estimation in the following link:
http://www.wolfdynamics.com/tools.html?id=2
856
A crash introduction to turbulence modeling in OpenFOAM®
where
Viscous length 857
A crash introduction to turbulence modeling in OpenFOAM®
• Similar to y+, the wall distance units can be computed in the stream-wise ( ) and
span-wise ( ) directions.
• DES and RANS simulations do not have stream-wise and span-wise wall distance units
requirements as in LES simulations. Therefore, they are more affordable.
• Typical requirements for LES are (these are approximations based on different references):
859
A crash introduction to turbulence modeling in OpenFOAM®
• Always monitor the turbulent variables, some of them are positive bounded.
• Avoid strong oscillations of the turbulent variables.
• If you are doing LES, remember that these models are intrinsically 3D and unsteady. You should
choose your time-step in such a way to get a CFL of less than 1 and preferably of about 0.5.
• If you are doing RANS with wall functions, it is perfectly fine to use upwind to discretize the
turbulence closure equations. After all, turbulence is a dissipative process. However, some
authors may disagree with this, make your own conclusions.
• On the other hand, if you are using a wall resolved approach, it is better to use a high-order
discretization scheme to discretize the turbulence closure equations.
• If you are doing unsteady simulations, always remember to compute the average values
(ensemble average).
• If you are dealing with external aerodynamics and detached flows, DES simulations are really
affordable.
• The work-horse of turbulence modeling in CFD, RANS
860
Turbulence modeling hands-on tutorials
$PTOFC/advanced_physics/turbulence/flatPlate
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
861
Turbulence modeling hands-on tutorials
Laminar-Turbulent flat plate
• The best way to understand the near the wall treatment and the effect of turbulence near the
walls, is by reproducing the law of the wall.
• By plotting the velocity in terms of the non-dimensional variables u+ and y+, we can compare
the profiles obtained from the simulations with the theoretical profiles. 862
Turbulence modeling hands-on tutorials
Laminar-Turbulent flat plate
• In the directory python of each case, you will find a jupyter notebook (a python script), that you
can use to plot the non-dimensional u+ and y+ profiles.
• The notebook uses some precomputed results, but you can adjust it to any case.
• Remember, the u+ vs. y+ plot is kind of a universal plot.
• It does not matter your geometry or flow conditions, if you are resolving well the turbulent flow,
you should be able to recover this profile.
• To compute this plot, you must sample the wall shear stresses and the velocity along a line
normal to the wall.
• Then, you can compute the shear velocity, friction coefficient, and u+ and y+ values.
863
Turbulence modeling hands-on tutorials
Laminar-Turbulent flat plate
• We are going to use the following solver: simpleFoam (for RANS).
• This case is rather simple, but we will use it to explain many features used in OpenFOAM®
when dealing with turbulence, especially when dealing with near the wall treatment.
• We will also show you how to do the post-processing in order to reproduce the law of the wall.
For this, we will use a jupyter notebook (a python script).
• Remember, as we are introducing new closure equations for the turbulence problem, we need to
define initial and boundary conditions for the new variables.
• We also need to define the discretization schemes and linear solvers to use to solve the new
variables.
• It is also a good idea to setup a few functionObjects, such as: y+, minimum and maximum
values, forces, time average, and online sampling.
• You will find the instructions of how to run this case in the file README.FIRST located in the
case directory.
864
Turbulence modeling hands-on tutorials
Laminar-Turbulent flat plate
• We select the turbulence model in the momentumTransport dictionary file.
• This dictionary file is located in the directory constant.
• To select the K-Omega SST turbulence model,
• Remember, you need to assign boundary and initial conditions to the new variables (k, omega,
and nut).
865
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
• To define the wall functions, follow this table,
omegaWallFunction omegaWallFunction
omega
$PTOFC/advanced_physics/turbulence/squarecil
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
way, you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
867
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
868
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
References:
Lyn, D.A. and Rodi, W., The flapping shear layer formed by flow separation from the forward corner of a square cylinder. J. Fluid Mech., 267, 353, 1994.
Lyn, D.A., Einav, S., Rodi, W. and Park, J.H., A laser-Doppler velocimetry study of ensemble-averaged characteristics of the turbulent near wake of a square
cylinder. Report. SFB 210 /E/100.
869
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
• We will use this case to learn how to setup a turbulent case (RANS and LES).
• To run this case we will use the solvers simpleFoam (steady solver) and pimpleFoam
(unsteady solver).
• To get fast outcomes, we will use a coarse mesh. But feel free to refine the mesh, especially
close to the walls.
• Remember, as we are introducing new closure equations for the turbulence problem, we need to
define initial and boundary conditions for the new variables.
• We will use a few functionObjects to compute some additional quantities, such as, Q criterion,
y+, minimum and maximum values, forces, time average, and online sampling.
• After finding the solution, we will visualize the results.
• We will also compare the numerical solution with the experimental results.
• At the end, we will do some plotting and advanced post-processing using gnuplot and Python.
• Have in mind that the unsteady case will generate a lot of data.
• You will find the instructions of how to run this case in the file README.FIRST located in the
case directory.
870
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
• We select the turbulence model in the momentumTransport dictionary file.
• This dictionary file is located in the directory constant.
• To select the LES (Smagorinsky) turbulence model,
27 delta cubeRootVol;
31 cubeRootVolCoeffs
LES filter
32 {
33 deltaCoeff 1;
34 }
100 }
• Remember, you need to assign boundary and initial conditions to the new variables (nut).
871
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
• To define the wall functions, follow this table,
omegaWallFunction omegaWallFunction
omega
• Run using the following combinations of wall functions and compare the outcome.
• Use High RE for RANS.
• Use High RE and Low RE for URANS.
• Use High RE and Low RE for LES.
872
Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder
• The initial value for the turbulent kinetic energy can be found as follows,
• The initial value for the specific kinetic energy can be found as follows,
• At this point, we are ready to run. But before running, remember to setup the right numerics in
the dictionary files fvSolution and fvSchemes.
• For the LES simulation, try to keep the CFL number below 0.9. For the URANS simulation, you
can go as high as 10.
• Finally, do not forget to setup the functionObjects to compute the forces, average values, do
the sampling, and compute y+ on-the-fly.
873
Roadmap
874
A crash introduction to multiphase flows modeling OpenFOAM®
875
A crash introduction to multiphase flows modeling OpenFOAM®
Propeller cavitation
http://www.veempropellers.com/features/cavitationresistance
Siltation & Sedimentation
http://blackwarriorriver.org/siltation-sedimentation/
876
A crash introduction to multiphase flows modeling OpenFOAM®
Fermentation of beer and spirits Chemical reactor for the pharmaceutical and
http://www.distillingliquor.com/2015/02/05/how-to-make-alcohol-and-spirits/ biotechnology industry
http://www.total-mechanical.com/Industrial/CaseStudies.aspx
877
A crash introduction to multiphase flows modeling OpenFOAM®
878
A crash introduction to multiphase flows modeling OpenFOAM®
• Disperse system: the phase is dispersed as non-contiguous isolated regions within the other
phase (the continuous phase) . When we work with a disperse phase, we say that the system is
dispersed: disperse-continuous flow.
• Separated system: the phase is contiguous throughout the domain and there is one well
defined interphase with the other phase. When we work with continuous phases, we say that the
system is separated: continuous-continuous flow.
879
A crash introduction to multiphase flows modeling OpenFOAM®
Increase
Modeling requirements
• Fully resolved: solves complete physics. All spatial and temporal scales
are resolved. Equivalent to DNS in turbulence modelling.
Computational power
transported with the flow. One- or two-way coupling is possible. It can
account for turbulence, momentum transfer, and mass transfer.
880
A crash introduction to multiphase flows modeling OpenFOAM®
VOF ≈ 0.5
Average phase
properties
In theory, the VOF method can resolve the smallest bubbles/droplets but the mesh requirements are
too prohibitive (equivalent to DNS). In multiphase flows, this is called fully resolved approach.
881
A crash introduction to multiphase flows modeling OpenFOAM®
882
A crash introduction to multiphase flows modeling OpenFOAM®
Eulerian-Eulerian Eulerian-Eulerian
Eulerian-Lagrangian
(VOF) (Dispersed systems)
885
A crash introduction to multiphase flows modeling OpenFOAM®
www.wolfdynamics.com/training/mphase/image10.gif http://www.wolfdynamics.com/training/mphase/image16.gif
http://www.wolfdynamics.com/training/mphase/image2.gif http://www.wolfdynamics.com/training/mphase/image3.gif
• Simulation showing free surface tracking, bubble tracking, bubble coalescence, bubble break-up and wake
entrainment using the VOF method.
• In this simulation the free surface and bubbles are capture by using AMR.
• However, the smallest bubble that can be resolved is at the smallest grid size. 887
A crash introduction to multiphase flows modeling OpenFOAM®
http://www.wolfdynamics.com/training/mphase/image18.gif
References:
[1] Vivek V. Buwa, Vivek V. Ranade, Dynamics of gas–liquid flow in a rectangular bubble column: experiments and single/multi-group CFD simulations.
Chemical Engineering Science 57 (2002) 4715 – 4736 888
A crash introduction to multiphase flows modeling OpenFOAM®
twoPhaseEulerFoam twoPhaseEulerFoam
Air volume fraction Air volume fraction
Turbulent case Laminar case
http://www.wolfdynamics.com/training/mphase/image42.gif http://www.wolfdynamics.com/training/mphase/image41.gif
DPMFoam twoPhaseEulerFoam
Particle-particle interactions colored by velocity Air volume fraction
magnitude (particles not to scale) Turbulent case
http://www.wolfdynamics.com/training/mphase/image43.gif http://www.wolfdynamics.com/training/mphase/image42.gif
Source terms:
• Porous media
• Coriolis forces
• Centrifugal forces
Surface tension - Continuum surface force (CSF) • Mass transfer
• and so on …
• You can see the volume fraction as a pointer that indicates what phase (with the
corresponding physical properties), is inside each cell of the computational domain. 891
A crash introduction to multiphase flows modeling OpenFOAM®
• The fluid properties can be written on either side of the interface as follows,
892
A crash introduction to multiphase flows modeling OpenFOAM®
Source terms:
• Porous media
• Coriolis forces
• Centrifugal forces
• Mass transfer
• and so on …
893
A crash introduction to multiphase flows modeling OpenFOAM®
896
Multiphase flows hands-on tutorials
$PTOFC/advanced_physics/multiphase/wigleyHull
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
897
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
Drag coefficient
899
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• We are going to use the following solver: interFoam
• The first step is to set the physical properties. In the dictionary
constant/transportProperties we defined the phases.
• Go to the directory constant and open the dictionary transportProperties.
The first phase is always considered the primary phase
900
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• The next step is to set the boundary conditions and initial conditions.
• Therefore, in the directory 0 we define the dictionary alpha.water that will take the values of
the phase water.
• In this case, you will find the directory 0_org, here is where we keep a backup of the original
files as we are doing field initialization using setFields.
• In the directory 0, you will find the dictionary p_rgh, in this dictionary we set the boundary and
initial conditions for the pressure field, and the dimensions are in Pascals.
• The turbulence variables values were calculated using an eddy viscosity ratio equal to 1,
turbulence intensity equal 5%, and the water properties.
• If you are simulating numerical towing tanks, the setup of the boundary conditions is always the
same.
• Feel free to reuse this setup.
• The dictionaries used in this case are standard for the VOF solvers (interFoam family solvers).
• If you are using a different solver (e.g., twoPhaseEulerFoam), you will need to use additional
dictionaries where you define the interfacial models and so on.
• Remember, you should always conduct production runs using a second order discretization
scheme
901
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
Opening
Air phase Wall
Inlet outlet
Note:
Phases must be initialized
on the internal cells and
boundary faces
Symmetry
Physical domain and boundary patches 902
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
fixedValue
inflow fixedFluxPressure fixedValue fixedValue
calculated (nut)
inletOutlet
outflow inletOutlet or zeroGradient outletPhaseMeanVelocity variableHeightFlowRate
calculated (nut)
inletOutlet
top totalPressure pressureInletOutletVelocity inletOutlet
calculated (nut)
kqRWallFunction (k)
ship fixedFluxPressure fixedValue omegaFunction (omega) zeroGradient
nutkWallFunction (nut)
Typical setup of boundary conditions for numerical towing tank simulations 903
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• OpenFOAM® solves the following modified volume fraction convective equation to track the
interface between the phases,
904
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• MULES options in the fvSolution dictionary.
• The semi-implicit MULES offers significant speed-up and stability over the explicit MULES.
“alpha.*”
{
MULESCorr yes; Turn on/off semi-implicit MULES
nAlphaSubCycles 1; For semi-implicit MULES use 1. Use 2 or more for
explicit MULES.
nAlphaCorr 3; Number of corrections.
Use 2-3 for slowly varying flows.
Use 3 or more for highly transient, high Reynolds,
high CFL number flows.
• If you are planning to use large time-steps (CFL number larger than 1), it is recommended to do
at least 3 nCorrector, otherwise you can use 2.
906
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• Finally, we need to set the discretization schemes
• This is done in the dictionary fvSchemes.
• In this dictionary we set the discretization method for every term appearing in the governing
equations.
• Convective terms discretization is set as follows:
divSchemes
{
This term is related to the
volume fraction equation
• Notice that we are using a high-resolution scheme for the surface tracking (div(phi,alpha)).
907
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• For time discretization we can use an unsteady formulation (Euler in this case).
• This scheme requires setting the time-step, and it should be choosing in such a way that it
resolves the mean physics.
• Remember, as the free surface is a strong discontinuity, for stability and good resolution we
need to use a CFL less than one for the interface courant.
ddtSchemes
{
default Euler;
}
• Hereafter, we are using what is know as global time stepping, that is, the CFL number is limited
by the smallest cell.
• The simulation is time-accurate, but it requires a lot of CPU time to reach a steady state (if it
reaches one).
908
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• A way to accelerate the convergence to steady state, is by using local time stepping (LTS).
• In LTS, the time-step is manipulated for each individual cell in the mesh, making it as high as
possible to enable the simulation to reach steady-state quickly.
• When we use LTS, the transient solution is no longer time accurate.
• The stability and accuracy of the method are driven by the local CFL number of each cell.
• To avoid instabilities caused by sudden changes in the time-step of each cell, the local time-
step can be smoothed and damped across the domain.
• Try to avoid having local time-steps that differ by several order of magnitudes.
• To enable LTS, we use the localEuler method.
ddtSchemes
{
default localEuler;
}
• LTS in OpenFOAM® can be used with any solver that supports the PISO or PIMPLE loop
(PISO ITA). 909
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• In the LTS method, the maximum flow CFL number, maximum interface CFL number, and the
smoothing and damping of the solution across the cells, can be controlled in the dictionary
fvSolution, in the sub-dictionary PIMPLE.
PIMPLE
{
momentumPredictor yes;
nOuterCorrectors 2;
nCorrector 3;
nNonOrthogonalCorrectors 2;
910
Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation
• At this point, we are ready to run the simulation.
• Remember to adjust the numerics according to your physics.
• You can choose between running using global time stepping or unsteady (directory uns) or local
time stepping (directory LTS).
• You will find the instructions of how to run the cases in the file README.FIRST located in the
case directory.
911
Roadmap
912
A crash introduction to compressible flows modeling OpenFOAM®
913
A crash introduction to compressible flows modeling OpenFOAM®
Large Natural Convection Plume, as effect of combustion of excess Rayleigh–Bénard convection cells
non-useable gases behind oilfield. https://en.wikipedia.org/wiki/File:B%C3%A9nard_cells_convection.ogv
https://en.wikipedia.org/wiki/Plume_(fluid_dynamics)#/media/File:Naturalc
onvectionplume.JPG
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose 915
A crash introduction to compressible flows modeling OpenFOAM®
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose 916
A crash introduction to compressible flows modeling OpenFOAM®
NSE
Additional closure equations for turbulence models, multiphase models, combustion, particles,
source terms, and so on
917
A crash introduction to compressible flows modeling OpenFOAM®
Thermal boundary layer vs. Viscous boundary layer Thermal boundary layer in function of Prandtl number (Pr)
Forced convection
• Just as there is a viscous (or momentum) boundary layer in the velocity distribution, there is also a thermal
boundary layer.
• Thermal boundary layer thickness is different from the thickness of the viscous sublayer (or momentum), and
is fluid dependent.
• The thickness of the thermal sublayer for a high Prandtl number fluid (e.g. water) is much less than the
momentum sublayer thickness.
• For fluids of low Prandtl numbers (e.g., air), it is much larger than the momentum sublayer thickness.
• For Prandtl number equal 1, the thermal boundary layer is equal to the momentum boundary layer. 918
A crash introduction to compressible flows modeling OpenFOAM®
Horizontal heated plate immersed in a quiescent fluid. Vertical heated plate immersed in a quiescent fluid.
Natural convection Natural convection.
• As the fluid is warmed by the plate, its density decreases, and a buoyant force arises which induces flow
motion in the vertical or horizontal direction.
• The force is proportional to , therefore gravity must be considered. 919
A crash introduction to compressible flows modeling OpenFOAM®
920
A crash introduction to compressible flows modeling OpenFOAM®
921
A crash introduction to compressible flows modeling OpenFOAM®
922
A crash introduction to compressible flows modeling OpenFOAM®
• High-speed aerodynamics:
• rhoSimpleFoam, rhoPimpleFoam, rhoCentralFoam
923
A crash introduction to compressible flows modeling OpenFOAM®
926
A crash introduction to compressible flows modeling OpenFOAM®
927
A crash introduction to compressible flows modeling OpenFOAM®
divSchemes “( | )”
{ {
div(phi,K) Gauss linear; solver PBiCGStab;
div(phi,h) Gauss linear; preconditioner DILU;
div(phid,p) Gauss linear; tolerance 1e-8;
… relTol 0.01;
… }
… …
} …
…
divSchemes “( | )”
{ {
div(phi,K) Gauss linear; solver PBiCGStab;
div(phi,e) Gauss linear; preconditioner DILU;
div(phiv,p) Gauss linear; tolerance 1e-8;
… relTol 0.01;
… }
… …
} …
…
Final remarks
• When solving the enthalpy formulation of the energy equation,
• This has a stabilizing effect on the solution, specially if you are using steady solvers.
• To turn off the pressure work term , set the option dpdt to no ( dpdt no; ) in the
thermophysicalProperties dictionary.
• Finally, when you work with compressible solvers you use absolute pressure
and the working units are in Pascals.
930
Compressible flows hands-on tutorials
$PTOFC/advanced_physics/compressible/supersonic_cyl
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
931
Compressible flows hands-on tutorials
2D supersonic cylinder – Shock waves
• Shock waves are strong discontinuities that need to be treated using high resolution schemes.
• Additionally, the non-orthogonality add extra complications to this problem.
932
Compressible flows hands-on tutorials
2D supersonic cylinder – Shock waves
933
Compressible flows hands-on tutorials
2D supersonic cylinder – Shock waves
• In this case we will use the solver rhoPimpleFoam with transonic corrections.
• By enabling transonic correction we can use this solver to tackle trans-sonic/supersonic flows.
• Transonic corrections are enabled in the PIMPLE block of the dictionary fvSolution,
• transonic yes;
• rhoPimpleFoam is an unsteady solver, but if you are interested in a steady solution you can
use local time stepping.
• As the flow is compressible, we need to define the thermodynamical properties of the working
fluid.
• This is done in the dictionary constant/thermophysicalProperties.
• We also need to define the boundary conditions and initial conditions for the temperature field.
• Additionally, if you are using a turbulence model, you will need to define wall functions for the
thermal diffusivity.
• The rest of the turbulent variables are defined as in incompressible flows.
• Finally, adjust the numerics according to your physics.
• You will find the instructions of how to run the cases in the file README.FIRST located in the
case directory.
934
Roadmap
935
A crash introduction to moving bodies OpenFOAM®
Prescribed motion with multiple bodies Layering with mesh zones interface
http://www.wolfdynamics.com/training/dynamicMeshes/meshMotion1 http://www.wolfdynamics.com/training/dynamicMeshes/layeringMesh.gif936
A crash introduction to moving bodies OpenFOAM®
• Setting moving bodies simulations is not so different from what we have done so far.
• The main difference is that we must assign a motion type to a surface patch, a cell region, or the
whole domain.
938
A crash introduction to moving bodies OpenFOAM®
939
A crash introduction to moving bodies OpenFOAM®
$PTOFC/advanced_physics/sliding_meshes_MRF/CSTR
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
941
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
942
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• We already created this mesh during the meshing module.
• We will only address the differences in meshing for an MRF simulation and a sliding mesh
simulation.
• In this case, at the end of the meshing stage we obtained a faceZone and a cellZone.
• This is a conforming mesh, that is, the cells in the interface of the inner and outer regions are
perfectly matching.
• For MRF simulations, the cellZone can be used to assign the MRF properties to the rotating
zone.
• For sliding meshes or non-conforming meshes, there is an extra step where we need to split the
mesh in two regions and create the interface patches between the fix zone and the rotating
zone (the solution will be interpolated in these patches).
Cell region 2
(fix region)s
943
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• In the MRF approach, the governing equations are solved in a relative rotating frame in the
selected rotating zone.
• Additional source terms that model the rotation effect are taken into account.
• You select the rotating zone and set the rotation properties in the dictionary
constant/MRFProperties.
• In this case, the mesh is conforming.
Shaft
type rotatingWallVelocity;
origin (0 0 0);
axis (0 0 1);
omega constant 12.566370;
value uniform (0 0 0);
Impeller
type movingWallVelocity;
value uniform (0 0 0); Inner region generated during
meshing - MRFProperties
944
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• In the sliding meshes approach, the selected rotating region is physically rotating.
• As the meshes are non-conforming, the solution between the rotating region and the fix region
must be interpolated using arbitrary mesh interface.
• In the sliding meshes approach, is not enough to only identify the rotating region.
• We also need to create the interface patches between the fix zone and the rotating zone.
Shaft
type rotatingWallVelocity;
origin (0 0 0);
axis (0 0 1);
omega constant 12.566370;
value uniform (0 0 0);
Impeller
type movingWallVelocity;
value uniform (0 0 0); Inner region – dynamicMeshDict
945
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
Shaft
type rotatingWallVelocity;
origin (0 0 0);
axis (0 0 1);
omega constant 12.566370;
value uniform (0 0 0);
Impeller
type movingWallVelocity;
value uniform (0 0 0); Inner region and arbitrary mesh
interface
cellZone cell_inner_volume;
dynamicFvMesh dynamicMotionSolverFvMesh; active yes;
motionSolverLibs ( "libfvMotionSolvers.so" );
solver solidBody; // Fixed patches (by default they move’ with the MRF zone)
cellZone cell_inner_volume; nonRotatingPatches ();
solidBodyMotionFunction rotatingMotion;
origin (0 0 0); origin (0 0 0);
axis (0 0 1); axis (0 0 1);
omega constant 12.566370; omega constant 12.566370;
946
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• For siding meshes, we need to create separated regions.
• In this case, to create the two regions we proceed as follows,
• In step 1, we split the mesh in regions using the baffles (faceZone), created during the meshing
stage.
• We also create the cyclicAMI patches AMI1 and AMI2.
• At this point we have two regions and one zone. However, the two regions are stich together
via the patches AMI1 and AMI2.
• In step 2, we topologically split the patches AMI1 and AMI2. As we removed the link between
AMI1 and AMI2, the regions are free to move.
947
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• The utility createBaffles, reads the dictionary createBafflesDict.
• With this utility we create the interface patches between the fix zone and the rotating zone.
baffles
{
rotating Name of the baffle group
{
type faceZone; Use faceZone
zoneName face_inner_volume; Face to use to construct the AMI patches.
The name was defined in snappyHexMeshDict
patches
{
master Parameters for the master patch
{
name AMI1; Name of the master patch (user defined)
Boundary condition type cyclicAMI;
for sliding grids matchTolerance 0.0001;
neighbourPatch AMI2; Neighbour patch (slave patch or AMI2)
transform none;
}
slave Parameters for the slave patch
{
Boundary condition name AMI2; Name of the slave patch (user defined)
type cyclicAMI;
for sliding grids matchTolerance 0.0001;
neighbourPatch AMI1; Neighbour patch (master patch or AMI1)
transform none;
}
}
}
} Initially, the master and slave patches
share a common face
948
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• In sliding mesh simulations, the solution is interpolated back-and-forth between the regions.
• The interpolation is done at the arbitrary mesh interface patches (AMI) .
• To reduce interpolation errors at the AMI patches, the meshes should be similar in the master
and slave patches.
http://www.wolfdynamics.com/training/movingbodies/image8.gif
949
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• At this point, the mesh is ready to use.
• You can visualize the mesh using paraFoam.
• If you use checkMesh, it will report that there are two regions.
• In the dictionary constant/dynamicsMeshDict we set which region will move and the
rotation parameters.
• To preview the region motion, in the terminal type:
• $> moveDynamicMesh
• To preview the region motion and check the quality of the AMI interfaces, in the terminal type:
• $> moveDynamicMesh -checkAMI -noFunctionObjects
• In our YouTube channel you can find a step-by-step video explaining this case.
950
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
Calculating AMI weights between owner patch: AMI1 and neighbour patch: AMI2
Number of faces in
AMI: Creating addressing and weights between 2476 source faces and 2476 target faces the AMI patches
AMI: Patch source sum(weights) min/max/average = 0.94746705, 1.0067199, 0.99994232 AMI1 patch weights
AMI: Patch target sum(weights) min/max/average = 0.94746692, 1.0004497, 0.99980782 AMI2 patch weights
…
…
…
951
Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF
• At this point, we are ready to run the simulation.
• You can choose between running using sliding meshes (directory sliding_piso) or MRF
(directory MRF_simple).
• You can use the solver pimpleFoam for sliding meshes and the solver simpleFoam for MRF.
• You can also use pimpleFoam (unsteady solution) for the MRF. However, it is not
computationally efficient, the idea of MRF is to reach a steady solution fast.
• You can also try pimpleFoam (with local time stepping (LTS).
• You will find the instructions of how to run the cases in the file README.FIRST located in the
case directory.
952
Moving bodies hands-on tutorials
$PTOFC/advanced_physics/prescribed_motion/oscillatingCylinder
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
953
Moving bodies hands-on tutorials
Oscillating cylinder – Prescribed motion
Moving boundary
http://www.wolfdynamics.com/training/movingbodies/image10.gif
954
Moving bodies hands-on tutorials
Oscillating cylinder – Prescribed motion
• In the dictionary constant/dynamicMeshDict we select the mesh morphing method and the
boundary patch that it is moving (lines 21 and 25, respectively).
• There are many mesh morphing methods implemented in OpenFOAM®.
• Mesh morphing is based in diffusing or propagating the mesh deformation all over the domain.
• You will need to find the best method for your case.
• The setup used in this case works fine most of the times.
37 in
38 {
39 type fixedValue;
40 value uniform (0 0 0);
41 }
42 cylinder
43 {
44 type oscillatingDisplacement;
45 amplitude ( 0 1 0 );
46 omega 6.28318;
47 value uniform ( 0 0 0 ); Dummy value for paraview
48 }
956
Moving bodies hands-on tutorials
Oscillating cylinder – Prescribed motion
• You must assign the boundary condition movingWallVelocity to all patches that are moving.
• This is done in the dictionary 0/U.
41 cylinder
42 {
43 type movingWallVelocity;
44 value uniform (0 0 0);
45 }
• And as usual, you will need to adjust the numerics according to your physics.
• In this case we need to solve the new fields cellDisplacement and diffusivity, which are
related to the mesh motion and morphing.
• In the dictionary fvSolution, you will need to add a linear solver for the field
cellDisplacement.
• In the dictionary fvSchemes, you will need to add the discretization schemes related to the
mesh morphing diffusion method, laplacian(diffusivity, cellDisplacement).
• If you are dealing with turbulence modeling the treatment of the wall functions is the same as if
you were working with fixed meshes. 957
Moving bodies hands-on tutorials
Oscillating cylinder – Prescribed motion
• At this point, we are ready to run the simulation.
• You will find the instructions of how to run the cases in the file README.FIRST located in the
case directory.
• Before running the simulation, you can check the mesh motion.
• During this check, you can use large time-steps as we re not computing the solution, we are
only interested in checking the motion.
• To check the mesh motion, type in the terminal:
958
Moving bodies hands-on tutorials
$PTOFC/advanced_physics/rigid_body_motion/floatingObject
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
959
Moving bodies hands-on tutorials
Floating body – Rigid body motion
ime/ s
http://www.wolfdynamics.com/training/movingbodies/image11.gif
t v s o ientation u (acos( ) /pi/ )
position
c
ime/ s
http://www.wolfdynamics.com/training/movingbodies/image12.gif
23 sixDoFRigidBodyMotionCoeffs
24 {
25 patches (floatingObject); Moving patch
26
Mesh deformation limits.
27 innerDistance 0.1;
The mesh will not be deformed in the fringe located within
28 outerDistance 0.4;
innerDistance and outerDistance (distance normal to the wall)
33 centreOfMass (0.5 0.5 0.5);
34 mass 5; Physical properties of the body
35 momentOfInertia (0.08 0.08 0.1);
innerDistance
Set it to zero if you do not want to apply mesh morphing to the inner region 962
Moving bodies hands-on tutorials
Floating body – Rigid body motion
• The dictionary constant/dynamicMeshDict (continuation).
50 constraints
51 {
55 fixedAxis
56 {
57 sixDoFRigidBodyMotionConstraint axis;
58 axis (0 1 0);
59 } Motion constraints
If you do not give any
63 fixedLine constraint, the body is free
64 { to move in all directions.
65 sixDoFRigidBodyMotionConstraint line;
66 centreOfRotation (0.5 0.5 0.5);
67 direction (0 0 1);
68 }
70 }
Body restraints
72 restraints
Restraints can be used to
73 {
damp the acceleration of the
body.
75 }
In this case, we are not
using restraints
77 }
963
Moving bodies hands-on tutorials
Floating body – Rigid body motion
• In the dictionary 0/pointDisplacement we select the body motion.
• For rigid body motion, the body motion is computed by the solver, therefore, we use the
boundary condition calculated.
33 floatingObject
34 {
35 type calculated;
36 value uniform (0 0 0);
37 }
• You must assign the boundary condition movingWallVelocity to all patches that are moving.
This is done in the dictionary 0/U.
33 floatingObject
34 {
35 type movingWallVelocity;
36 value uniform (0 0 0);
37 }
• If you are dealing with turbulence modeling the treatment of the wall functions is the same as if
you were working with fixed meshes. 964
Moving bodies hands-on tutorials
Floating body – Rigid body motion
• And as usual, you will need to adjust the numerics according to your physics.
• In the case directory, you will find the script extractData.
• This script can be used to extract the position of the body during the simulation.
• In order to use the extractData script, you will need to save the log file of the simulation.
• At this point, we are ready to run the simulation.
• We will use the solver interFoam.
• You will find the instructions of how to run the cases in the file README.FIRST located in the
case directory.
965
Roadmap
966
A crash introduction to source terms OpenFOAM®
967
A crash introduction to source terms OpenFOAM®
Set of cell
Point selection
968
A crash introduction to source terms OpenFOAM®
23 }
• Remember, you can use the banana method to know all
24 } source terms and options available.
• You can also read the source code.
969
Source terms hands-on tutorials
$PTOFC/advanced_physics/source_terms/filter/porous_source
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
970
Source terms hands-on tutorials
Filter source term
• In this case we are going to use the source term explicitPorositySource.
• Using this source term we can apply a porous region (e.g., Darcy-Forchheimer) in the cell
selection.
• The source term is activated after 2 seconds of simulation time.
Set of cell
(filter)
http://www.wolfdynamics.com/training/sourceterms/image1.gif 971
Source terms hands-on tutorials
Filter source term
system/fvOptions
• The source terms can be selected in the
17
18
filter1
{
dictionary fvOptions, and they can be modified
19 type explicitPorositySource; on-the-fly.
20 active yes;
22 explicitPorositySourceCoeffs • In this case we are using the source term
23 {
25 timeStart 2; explicitPorositySource (line 19).
26 duration 5;
28 selectionMode cellZone; • Using this source term we can apply a porous
29 cellZone filter; region (of the type Darcy-Forchheimer) in the cell
31 type DarcyForchheimer;
selection (line 28).
38 DarcyForchheimerCoeffs
39 { • The source term is used in a cellZone (line 28)
41
44
d
f
(5000000 5000000 5000000);
(0 0 0);
named filter (line 29), this zone must be created
46 coordinateSystem at meshing time or using the utility topoSet.
47 {
49 type cartesian; • In lines 38-60, we define the input parameters of
50 origin (0 0 0);
52 coordinateRotation
the model.
53 {
54 type axesRotation;
• In this case, the coefficients f and d are
55 e1 (1 0 0); resistance/impermiability coefficients, and e1 and
56 e2 (0 1 0);
57 }
e2 are the vectors that are used to specify the
59 } porosity.
60 }
61 }
62 }
972
Source terms hands-on tutorials
Filter source term
system/topoSetDict
• To create the cellZone used in fvOptions, we
first create a cellSet.
• The set of cells (cellSet) is constructed using the
utility topoSet.
• This utility reads the dictionary topoSetDict,
which is located in the directory system.
974
Source terms hands-on tutorials
Filter source term
975
Roadmap
976
Scalar transport pluggable solver
977
Scalar transport pluggable solver
enabled true;
writeControl outputTime;
Number of corrector iterations.
log yes; It is recommended to do t least one iteration.
nCorr 1;
Diffusion coefficient.
D 0; If turbulent modeling is in use, you can define the
//alphaD 0; laminar diffusion coefficient alphaD and the turbulent
//alphaDt 0; diffusion coefficient alphaDt
Boundary conditions
0/s1
• Assuming that you named the new scalar s1, you
dimensions [0 0 0 0 0 0 0]; will need to define the boundary conditions and
initial conditions for the field s1.
internalField uniform 0;
• This is done in the dictionary 0/s1.
boundaryField
{ • In this case, the scalar is entering in the patch
walls
{ inlet with a value of 1 (this is a concentration
type zeroGradient; therefore it has no dimensions).
}
inlet
• The initial concentration of the scalar is zero.
{
type fixedValue;
value uniform 1;
}
outlet
{
type inletOutlet;
inletValue uniform 0;
value uniform 0;
}
}
979
Scalar transport pluggable solver
system/fvSchemes system/fvSolution
gradSchemes s1
{ {
default Gauss linear; solver smoothSolver;
grad(s1) cellLimited Gauss linear 1; smoother symGaussSeidel;
} tolerance 1e-08;
relTol 0;
}
divSchemes
{
default none;
div(phi,U) Gauss linearUpwindV default;
div(phi,s1) Gauss vanLeer;
}
980
Scalar transport pluggable solver hands-on tutorials
$PTOFC/advanced_physics/source_terms/2Delbow_passive_scalar
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
how to run the case. In this file, you might also find some additional comments.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
automatically by typing in the terminal, for example, sh run_solver.
• We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
you will get used with the command line interface and OpenFOAM® commands.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
981
Scalar transport pluggable solver hands-on tutorials
Scalar transport in an elbow – Internal geometry
• Notice that we are adding two scalars, s1 and s2.
S1
U → (2 0 0)
http://www.wolfdynamics.com/training/sourceterms/image2.gif
S2
U → (0 3 0)
http://www.wolfdynamics.com/training/sourceterms/image3.gif 982
Scalar transport pluggable solver hands-on tutorials
Scalar transport in an elbow – Internal geometry
• At this point, we are ready to run the simulation.
• We will use the solver pisoFoam.
• Remember to adjust the numerics according to your physics.
• Do not forget to create the boundary conditions and initial conditions of the new field variables.
• You will find the instructions of how to run the cases in the file README.FIRST located in the
case directory.
983
This is the end