[go: up one dir, main page]

0% found this document useful (0 votes)
1K views252 pages

Openfoam 2x2 PDF

Uploaded by

Akash Jadhav
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views252 pages

Openfoam 2x2 PDF

Uploaded by

Akash Jadhav
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 252

University of Genoa, DICCA

Dipartimento di Ingegneria Civile, Chimica e Ambientale

This work is licensed under a Creative Commons


Attribution-ShareAlike 4.0 International License (CC BY-SA 4.0)

Introductory OpenFOAM® Course To view a copy of this license, visit


http://creativecommons.org/licenses/by-sa/4.0/
From 8th to 12th July, 2019

• A help is needed, and much appreciated.


• If you find errors, have suggestions for better wording, figures, or new material, let us know.
• Also, if you find a tutorial that does not work, please let us know.
• Follow-up problems, questions, and suggestions at guerrero@wolfdynamics.com

Disclaimer Acknowledgements

This offering is not approved or endorsed by OpenCFD Limited, the This training material and tutorials are based upon personal experience, OpenFOAM® source
code, OpenFOAM® user guide, OpenFOAM® programmer’s guide, and presentations from
producer of the OpenFOAM software and owner of the OPENFOAM® and
previous OpenFOAM® training sessions and OpenFOAM® workshops.
OpenCFD® trade marks.
We gratefully acknowledge the following OpenFOAM® users for sharing online their material or for
giving us their consent to use their material:

• Henry Weller and Chris Greenshields. The OpenFOAM Foundation.


Wolf Dynamics makes no warranty, express or implied, about the • Hrvoje Jasak and Henrik Rusche. Wikki Ltd.
completeness, accuracy, reliability, suitability, or usefulness of the • Eugene de Villiers, Paolo Geremia, and Dan Combest. Engys.
information disclosed in this training material. This training material is • Hakan Nilsson. Chalmers University of Technology.
intended to provide general information only. Any reliance the final user • Eric Paterson. Pennsylvania State University.
place on this training material is therefore strictly at his/her own risk. Under • Gavin Tabor. University of Exeter.
no circumstances and under no legal theory shall Wolf Dynamics be liable • Fumiya Nozaki. Yokohama, Japan.
for any loss, damage or injury, arising directly or indirectly from the use or • Marwan Darwish. American University of Beirut.
misuse of the information contained in this training material. • Kevin Maki. University of Michigan.

Revision 1-2019
Joel Guerrero
On the training material On the training material
The following typographical conventions are used in this The following typographical conventions are used in this
training material training material
• Text in Courier new font indicates Linux commands that should be typed literally by the user
• Large code listing, ascii files listing, and screen outputs can be written in
in the terminal.
a square box, as follows:
• Text in Courier new bold font indicates directories.
• Text in Courier new italic font indicates human readable files or ascii files.
1 #include <iostream>
• Text in Arial bold font indicates program elements such as variables, function names, classes, 2 using namespace std;
statements and so on. It also indicate environment variables, and keywords. They also 3
4 // main() is where program execution begins. It is the main function.
highlight important information.
5 // Every program in c++ must have this main function declared
• Text in Arial underline in blue font indicates URLs and email addresses. 6
7 int main ()
• This icon indicates a warning or a caution. 8 {
• This icon indicates a tip, suggestion, or a general note. 9 cout << "Hello world"; //prints Hello world
10 return 0; //returns nothing
• This icon indicates a folder or directory. 11 }
• This icon indicates a human readable file (ascii file).
• This icon indicates that the figure is an animation (animated gif). • To improve readability, the text might be colored.
• These characters $> indicate that a Linux command should be typed literally by the user in the • The font can be Courier new or Arial bold.
terminal.
• And when required, the line number will be shown.

On the training material On the training material


Training material Exercises
• In the USB key you will find all the training material (tutorials, slides, quick reference guides, OpenFOAM® • At the end of each section, you will find an exercise section.
user guide, OpenFOAM® programmers manual, and lectures notes).
• You can also download the training material in the following link,
• The exercise section is optional, self-paced, and do it at anytime.
http://www.wolfdynamics.com/images/OF_intro_training/6x.tar.gz
• The proposed exercises are designed to test your knowledge and to
• You can extract the training material wherever you want. However, we highly recommend to extract all the
training material in your OpenFOAM® user directory. reinforce the concepts addressed during the lectures.
• From now on, we will refer to the directory where you extracted the training material as, • All the concepts to be addressed in the exercise sections have been treated
• $PTOFC
(abbreviation of Path To OpenFOAM® Course) in the lecture notes, so the reader should not have problems answering the
• To uncompress the tutorials go to the directory where you copied the training material and then type in the questions.
terminal,
• $> tar –zxvf file_name.tar.gz • If you have doubts, do not hesitate in asking.
• In every single tutorial, you will find the file README.FIRST. In this file you will find the general instructions of • To help you answering the exercises, we might give you a few tips.
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 • And if it is necessary, the solution will be given.
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.
Training agenda Training agenda
Module 0. Module 5.
• Training agenda • Sampling and plotting
• On the training material • Data conversion
• Housekeeping issues
• Additional information Module 6.
• The finite volume method. A crash introduction
Module 1. • On the CFL number
• Introduction to OpenFOAM® • Boundary conditions and initial conditions
• A few OpenFOAM® simulations • Unsteady and steady simulations
• Library organization • Assessing convergence
• OpenFOAM® 101 – My first tutorial • Velocity pressure-coupling
• Linear solvers
Module 2.
Module 7.
• Solid modeling for CFD
• Implementing boundary conditions and initial conditions using
codeStream
Module 3.
• Meshing preliminaries Module 8.
• Mesh quality assessment • Advanced modeling capabilities:
• Meshing in OpenFOAM® – blockMesh and snappyHexMesh • Turbulence modeling
• The training agenda is organized in such a way that we will address the whole CFD simulation workflow.
• Mesh conversion and manipulation • Multiphase flows
• Compressible flows
• The starting point of every CFD workflow is the geometry.
Module 4. • Moving reference frames and sliding grids • Then we proceed to generate the mesh and assign the boundaries surface patches.
• Running in parallel • Moving bodies and rigid body motion • After we have a valid mesh, we proceed to the case setup and we launch/monitor the simulation.
• Source terms and passive scalars • At the end, we do the post-processing (quantitative and qualitative).

Roadmap

1. OpenFOAM® brief overview


2. OpenFOAM® directory organization
3. Directory structure of an application/utility
Module 1 4. Applications/utilities in OpenFOAM®
OpenFOAM® overview – First tutorial – 5. Directory structure of an OpenFOAM® case
Working our way in OpenFOAM® 6. Running my first OpenFOAM® case setup blindfold
7. A deeper view to my first OpenFOAM® case setup
8. 3D Dam break – Free surface flow
9. Flow past a cylinder – From laminar to turbulent flow

1 2
OpenFOAM® brief overview OpenFOAM® brief overview
General description: Multi-physics simulation capabilities:
• OpenFOAM® stands for Open Source Field Operation and Manipulation. • OpenFOAM® has extensive multi-physics simulation capabilities, among
others:
• OpenFOAM® is first and foremost a C++ library used to solve partial
differential equations (PDEs), and ordinary differential equations (ODEs). • Computational fluid dynamics (incompressible and compressible flows).
• It comes with several ready-to-use or out-of-the-box solvers, pre-processing • Computational heat transfer and conjugate heat transfer.
utilities, and post-processing utilities.
• Combustion and chemical reactions.
• It is licensed under the GNU General Public License (GPL). That means it is
• Multiphase flows and mass transfer.
freely available and distributed with the source code.
• Particle methods (DEM, DSMC, MD) and lagrangian particles tracking.
• It can be used in massively parallel computers. No need to pay for separate
licenses. • Stress analysis and fluid-structure interaction.
• It is under active development. • Rotating frames of reference, arbitrary mesh interface, dynamic mesh
handling, and adaptive mesh refinement.
• It counts with a wide-spread community around the world (industry,
academia and research labs). • 6 DOF solvers, ODE solvers, computational aero-acoustics,
computational electromagnetics, computational solid mechanics, MHD.

3 4

OpenFOAM® brief overview OpenFOAM® brief overview


Physical modeling library: Under the hood you will find the following:
• OpenFOAM® comes with many physical models, among others: • Finite Volume Method (FVM) based solver.
• Extensive turbulence modeling capabilities (RANS, DES and LES). • Collocated polyhedral unstructured meshes.
• Transport/rheology models. Newtonian and non-Newtonian viscosity • Second order accuracy in space and time. Many discretization schemes
models. available (including high order methods).

• Thermophysical models and physical properties for liquids and gases. • Steady and transient solvers available.

• Source terms models. • Pressure-velocity coupling via segregated methods (SIMPLE and PISO).
• But coupled solvers are under active development.
• Lagrangian particle models.
• Massive parallelism through domain decomposition.
• Interphase momentum transfer models for multiphase flows.
• It comes with its own mesh generation tools.
• Combustion, flame speed, chemical reactions, porous media, radiation,
phase change. • 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.
5 6
OpenFOAM® brief overview OpenFOAM® brief overview
OpenFOAM® vs. Commercial CFD applications: Developing new solvers (in case you need it):
• OpenFOAM® capabilities mirror those of commercial CFD applications. • As the user has complete access to the source code, he/she has total
• The main differences with commercial CFD applications are: freedom to modify existing solvers or use them as the starting point for new
• There is no native GUI. solvers.
• It does not come with predefined setups. The users need to have a basic • New solvers can be easily implemented using OpenFOAM® high level
understanding of the CFD basics and be familiar with OpenFOAM® command programming, e.g.:
line interface (CLI).
• Knowing your way around the Linux bash shell is extremely useful.
solve
• It is not a single executable. Depending of what you are looking for, you will (
need to execute a specific application from the CLI. fvm::ddt(T)
+ fvm::div(phi,T)
• It is not well documented, but the source code is available. - fvm::laplacian(nu,T)
==
• Access to complete source = no black magic. But to understand the source 0
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. Correspondence between the implementation and the original equation is clear.

7 8

OpenFOAM® brief overview Roadmap

1. OpenFOAM® brief overview


2. OpenFOAM® directory organization
3. Directory structure of an application/utility
OpenFOAM® is an excellent piece of C++ 4. Applications/utilities in OpenFOAM®
and software engineering. Decent piece of 5. Directory structure of an OpenFOAM® case
CFD code. 6. Running my first OpenFOAM® case setup blindfold
H. Jasak 7. A deeper view to my first OpenFOAM® case setup
8. 3D Dam break – Free surface flow
9. Flow past a cylinder – From laminar to turbulent flow

9 10
OpenFOAM® directory organization OpenFOAM® directory organization
$WM_PROJECT_DIR If you installed OpenFOAM® in the default location, the $WM_PROJECT_DIR OpenFOAM® environment variables
├── Allwmake directory the environment variable $WM_PROJECT_DIR ├── Allwmake
├── applications should point to the following directory (depending on the ├── applications The entries starting with the symbol $ are environment
installed version):
├── bin ├── bin variables. You can find out the value of an environment
├── COPYING ├── COPYING variable by echoing its value, for example:
├── doc $HOME/OpenFOAM/OpenFOAM-6 ├── doc $> echo $WM_PROJECT_DIR
├── etc or ├── etc
├── platforms $HOME/OpenFOAM/OpenFOAM-dev ├── platforms
will give you the following output on the terminal
├── README.org ├── README.org
$HOME/OpenFOAM/OpenFOAM-6
├── src In this directory you will find all the directories containing
├── src
├── tutorials OpenFOAM® installation. ├── tutorials
└── wmake └── wmake To list all the environment variables type in the terminal
window env
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®. To list all the environment variables related to
OpenFOAM®, type in the terminal:
$> env | grep “OpenFOAM”

11 12

OpenFOAM® directory organization OpenFOAM® directory organization


$WM_PROJECT_DIR OpenFOAM® aliases $WM_PROJECT_DIR
├── Allwmake ├── Allwmake Let us study each directory inside
├── applications ├── applications
├── bin
You can go to any of these directories by using the
├── bin $WM_PROJECT_DIR
predefined aliases set by OpenFOAM® (see
├── COPYING $WM_PROJECT_DIR/etc/config/alias.sh). Just to ├── COPYING
├── doc name a few of the aliases defined: ├── doc
├── etc alias foam=‘cd $WM_PROJECT_DIR’ ├── etc
├── platforms alias app=‘cd $FOAM_APP’ ├── platforms
├── README.org alias src=‘cd $FOAM_SRC’ ├── README.org • Any modification you add to the source code in
├── src ├── src WM_PROJECT_DIR will affect the whole library.
alias tut=‘cd $FOAM_TUTORIALS’
├── tutorials ├── tutorials • Unless you know what are you doing, do not
└── wmake └── wmake modify anything in the original installation
For a complete list type alias in the terminal. ($WM_PROJECT_DIR), except for updates!

To list all the aliases related to OpenFOAM®, type in the


terminal:
$> alias | grep “FOAM”

13 14
OpenFOAM® directory organization OpenFOAM® directory organization
The applications directory The bin directory
$WM_PROJECT_DIR/applications $WM_PROJECT_DIR/bin/ Let us visit the bin directory:
├── Allwmake ├── foamCleanPolyMesh
├── solvers • The bin directory contains many shell
├── foamCleanTutorials scripts, such as foamNew, foamLog,
├── test ├── foamCloneCase foamJob, foamNewApp, etc.
└── utilities ├── foamJob
├── foamLog • This directory also contains the script
paraFoam that will launch paraView.
├── foamMonitor
Let us visit the applications directory. Type in the terminal app or ├── foamNew
$> cd $WM_PROJECT_DIR/applications. You will find the following sub-directories: ├── foamNewApp
• solvers, which contains the source code for the distributed solvers. ├── foamNewBC
• test, which contains the source code of several test cases that show the usage of ├── foamNewFunctionObject
some of the OpenFOAM® classes. ├── paraFoam
• utilities, which contains the source code for the distributed utilities. ├── ...
There is also an Allwmake script, which will compile all the content of solvers and └── tools
utilities. To compile the test cases in test go to the desired test case directory and
compile it by typing wmake.

The directory tree is not complete


15 16

OpenFOAM® directory organization OpenFOAM® directory organization


The doc directory The etc directory
$WM_PROJECT_DIR/doc/ Let us visit the doc directory: $WM_PROJECT_DIR/etc/ Let us visit the etc directory:
├── Allwmake ├── bashrc
• The doc directory contains the documentation • The etc directory contains the environment
├── codingStyleGuide.org ├── caseDicts
of OpenFOAM®, namely; user guide, files, global OpenFOAM® instructions,
├── Doxygen programmer’s guide and Doxygen generated ├── cellModels templates, and the default thermochemical
├── Guides documentation in html format. ├── codeTemplates database thermoData/thermoData
└── tools ├── config.csh
• The Doxygen documentation needs to be ├── config.sh • It also contains the super dictionary
compiled by typing Allwmake doc in controlDict, where you can set several
$WM_PROJECT_DIR. ├── controlDict debug flags and the defaults units.
├── cshrc
• You can access the Doxygen documentation ├── README.org
online, http://cpp.openfoam.org/v5 ├── templates
└── thermoData

17 18
OpenFOAM® directory organization OpenFOAM® directory organization
The platforms directory The src directory
$WM_PROJECT_DIR/platforms/ $WM_PROJECT_DIR/src Let us visit the src directory. Type in the terminal
├── linux64GccDPInt32Opt ├── Allwmake src or $> cd $WM_PROJECT_DIR/src
│ ├── applications ├── combustionModels
│ ├── bin ├── finiteVolume • This directory contains the source code for all
│ ├── lib ├── fvOptions the foundation libraries, this is the core of
│ └── src ├── lagrangian OpenFOAM®.
└── linux64GccDPInt32OptSYSTEMOPENMPI ├── ... • It is divided in different subdirectories and each
└── src ├── OpenFOAM of them can contain several libraries.
├── parallel
Let us visit the platforms directory. ├── sampling A few interesting directories are:
• This directory contains the binaries generated when compiling the applications ├── sixDoFRigidBodyMotion • OpenFOAM. This core library includes the
directory and the libraries generated by compiling the source code in the src directory.
├── thermophysicalModels definitions of the containers used for the
• After compilation, the binaries will be located in the directory ├── transportModels operations, the field definitions, the declaration
$WM_PROJECT_DIR/platforms/linux64GccDPInt32OptSYSTEMOPENMPI/bin of the mesh and mesh features such as zones
$WM_PROJECT_DIR/platforms/linux64GccDPOpt/lib).
├── TurbulenceModels
and sets.
└── waves
• After compilation, the libraries will be located in the directory
$WM_PROJECT_DIR/platforms/linux64GccDPInt32OptSYSTEMOPENMPI/lib
The directory tree is not complete
19 20

OpenFOAM® directory organization OpenFOAM® directory organization


The src directory The tutorials directory
$WM_PROJECT_DIR/src A few interesting directories are:
$WM_PROJECT_DIR/tutorials/ Let us visit the tutorials directory. Type in the
├── Allwmake ├── Allclean terminal tut or
• finiteVolume. This library provides all the
├── combustionModels ├── Allrun $> cd $WM_PROJECT_DIR/tutorials
classes needed for the finite volume
├── finiteVolume discretization, such as mesh handling, finite
├── Alltest
├── basic
├── fvOptions volume discretization operators (divergence,
• The tutorials directory contains example
laplacian, gradient, fvc/fvm and so on), and ├── combustion
├── lagrangian boundary conditions. In the directory ├── compressible cases for each solver. These are the tutorials
├── ... finiteVolume/lnInclude you also find the ├── discreteMethods distributed with OpenFOAM®.
├── OpenFOAM very important file fvCFD.H, which is included ├── DNS
• They are organized according to the physics
├── parallel in most applications. ├── electromagnetics
involved.
├── sampling • sixDoFRigidBodyMotion. This core library ├── financial
├── sixDoFRigidBodyMotion contains the solver for rigid body motion. ├── heatTransfer • Use these tutorials as the starting point to
├── thermophysicalModels • transportModels. This core library contains ├── incompressible develop you own cases.
├── transportModels many transport models. ├── IO
• TurbulenceModels, which contains many ├── lagrangian • A word of caution, do not use these tutorials
├── TurbulenceModels
turbulence models. ├── mesh as best practices, they are there just to show
└── waves ├── multiphase how to use the applications.
├── resources
The directory tree is not complete
21
└── stressAnalysis 22
OpenFOAM® directory organization OpenFOAM® directory organization
The wmake directory OpenFOAM® user directory
$WM_PROJECT_DIR/wmake/ Let us visit the wmake directory. $HOME/OpenFOAM/
├── makefiles
├── platforms
├── $WM_PROJECT_USER_DIR
• OpenFOAM® uses a special make
├── rules command: wmake └── $WM_PROJECT_DIR
├── scripts
├── src • wmake understands the file structure in
├── wclean OpenFOAM® and uses default compiler • Let us now study OpenFOAM® user directory $WM_PROJECT_USER_DIR
├── wcleanLnIncludeAll directives set in this directory. • When working with OpenFOAM®, you can put your files wherever you want.
├── wcleanPlatform • To keep things in order, it is recommended to put your cases in your
• If you add a new compiler name in
├── wdep OpenFOAM® bashrc file, you should also OpenFOAM® user directory or $WM_PROJECT_USER_DIR.
├── ... tell wmake how to interpret that name. In
├── wmake wmake/rules you will find the default • It is also recommended to put your modified solvers, utilities, and libraries in
├── wmakeFilesAndOptions settings for the available compilers. your OpenFOAM® user directory or $WM_PROJECT_USER_DIR. This is done so
├── wmakeLnInclude you do not modify anything in the original installation.
├── wmakeLnIncludeAll • You will also find a few scripts that are • If you followed the standard installation instructions, the variable
└── wrmo useful when organizing your files for $WM_PROJECT_USER_DIR should point to the directory
compilation, or for cleaning up.
$HOME/OpenFOAM/USER_NAME-6, where USER_NAME is the name of the
user (e.g., johnDoe).
The directory tree is not complete
23 24

OpenFOAM® directory organization OpenFOAM® directory organization


Looking for information in OpenFOAM® source code Looking for information in OpenFOAM® source code
• To locate files you can use the find command. • Dictionaries are input files required by OpenFOAM®.
• If you want to locate a directory inside $WM_PROJECT_DIR that contains the string fvPatch in • As you can imagine, there are many dictionaries in OpenFOAM®. The easiest way to find all of
its name, you can proceed as follows, them is to do a local search in the installation directory as follows,
• $> find $WM_PROJECT_DIR –type d -name “*fvPatch*” • 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:
Where to look for Look for Case Look for this
directories sensitive (using wildcards) • $> find $FOAM_TUTORIALS -name “*Dict”
(Case sensitive search)
• If you want to locate a file inside $WM_PROJECT_DIR that contains the string fvPatch in its
• $> find $FOAM_TUTORIALS –iname ‘*dict’
name, you can proceed as follows,
(Non-case sensitive search)
• $> find $WM_PROJECT_DIR –type f -name “*fvPatch*”

Where to look for Look for Case Look for this • When given the search string, you can use single quotes ‘ ’ or double-quotes “ ” (do not mixed
files sensitive (using wildcards)
them).
• If you want to find a string inside a file, you can use the grep command. • We recommend to use single quotes, but it is up to you.
• 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 26
OpenFOAM® directory organization OpenFOAM® directory organization
Looking for information in OpenFOAM® source code Environment variables
• A few more advanced commands to find information in your OpenFOAM® installation. • Remember, OpenFOAM® uses its own environment variables.

• To find which tutorial files use the boundary condition slip: • OpenFOAM® environment settings are contained in the OpenFOAM-6/etc directory.

• $> find $FOAM_TUTORIALS -type f | xargs grep -sl ‘ slip’ • If you installed OpenFOAM® in the default location, they should be in:
This command will look for all files inside the directory $FOAM_TUTORIALS, then the • $HOME/OpenFOAM/OpenFOAM-6/etc
output is used by grep to search for the string slip. • 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:
• To find where the source code for the boundary condition slip is located:
• source $HOME/OpenFOAM/OpenFOAM-6/etc/bashrc
• $> find $FOAM_SRC -name “*slip*”

• By sourcing the file $WM_PROJECT_DIR/etc/bashrc, we start to use OpenFOAM®


• To find what applications do not run in parallel: environment variables.
• $> find $WM_PROJECT_DIR -type f | xargs grep -sl ‘noParallel’ • By default, OpenFOAM® uses the system compiler and the system MPI compiler.
• When you use OpenFOAM® you are using its environment settings, that is, its
• OpenFOAM® understands REGEX syntax. path to libraries and compilers. So if you are doing software developing, and
you are having compilation problems due to conflicting libraries or missing
compilers, try to unload OpenFOAM® environment variables

27 28

Roadmap Directory structure of an OpenFOAM® application/utility

Directory structure of a general solver


1. OpenFOAM® brief overview $WM_PROJECT_DIR/applications/solvers/solverName/
├── createFields.H
2. OpenFOAM® directory organization ├── appName.C
3. Directory structure of an application/utility └── Make
├── files
4. Applications/utilities in OpenFOAM® └── options
5. Directory structure of an OpenFOAM® case
6. Running my first OpenFOAM® case setup blindfold The $WM_PROJECT_DIR/applications/solvers/solverName/ directory contains the
source code of the solver.
7. A deeper view to my first OpenFOAM® case setup • solverName/appName.C: is the actual source code of the solver.

8. 3D Dam break – Free surface flow • solverName/createFields.H: declares all the field variables and initializes the solution.
• The Make directory contains compilation instructions.
9. Flow past a cylinder – From laminar to turbulent flow
• Make/files: names all the source files (.C), it specifies the solverName name and
location of the output file.
• Make/options: specifies directories to search for include files and libraries to link the
solver against.
29 30
Directory structure of an OpenFOAM® application/utility Directory structure of an OpenFOAM® application/utility

Directory structure of a general utility • For your own solvers and utilities, it is recommended to put the source code
in the directory $WM_PROJECT_USER_DIR following the same structure as
applications/utilities/utilityName/ in $WM_PROJECT_DIR/applications/solvers and
├── utility_dictionary $WM_PROJECT_DIR/utilities/.
├── utilityName.C
├── header_files.H • Also, you will need to modify the files Make/files and Make/options to
└── Make point to the new name and location of the compiled binaries and libraries to
├── files link the solver against.
└── options
• You can do anything you want to your own copies, so you do not risk
messing things up.
The $WM_PROJECT_DIR/utilities/utilityName/ directory contains the source code of
the utility. • This is done so you do not modify anything in the original installation, except
• utilityName/utilityName.C: is the actual source code of the application. for updates!
• utilityName/header_files.H: header files required to compile the application.
• utilityName/utility_dictionary: application’s master dictionary.
• The Make directory contains compilation instructions.
• Make/files: names all the source files (.C), it specifies the utilityName name
and location of the output file.
• Make/options: specifies directories to search for include files and libraries to link the
solver against. 31 32

Roadmap 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
1. OpenFOAM® brief overview there are many of them.
2. OpenFOAM® directory organization • 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
3. Directory structure of an application/utility guide (chapter 3). In the directory $WM_PROJECT_DIR/doc you will find the
4. Applications/utilities in OpenFOAM® documentation in pdf format.
• You can also access the online user guide. Go to the link
5. Directory structure of an OpenFOAM® case http://cfd.direct/openfoam/user-guide/#contents, then go to chapter 3 (applications
6. Running my first OpenFOAM® case setup blindfold and libraries).
• If you want to get help on how to run an application, type in terminal
7. A deeper view to my first OpenFOAM® case setup
8. 3D Dam break – Free surface flow 1. $> application_name -help

9. Flow past a cylinder – From laminar to turbulent flow


• 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.
33 34
Applications/utilities in OpenFOAM® Applications/utilities in OpenFOAM®
• You will find all the applications in the directory $FOAM_SOLVERS (use alias sol to • For example, in the sub-directory incompressible you will find several sub-
go there). directories containing the source code of the following solvers:
• You will find all the utilities in the directory $FOAM_UTILITIES (use alias util to go
there). • adjointShapeOptimizationFoam • pimpleFoam
• For example, in the directory $FOAM_SOLVERS, you will find the directories containing • boundaryFoam • pisoFoam
the source code for the solvers available in the OpenFOAM® installation (version 6): • icoFoam • shallowWaterFoam
• nonNewtonianIcoFoam • simpleFoam
• basic • financial
• combustion • heatTransfer • Inside each directory, you will find a file with the extension *.C and the same name
• compressible • incompressible 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.
• discreteMethods • lagrangian
• For example, in the file incompressible/icoFoam/icoFoam.C you will find the
• DNS • multiphase
following description:
• electromagnetics • stressAnalysis

Transient solver for incompressible, laminar flow of Newtonian fluids.


• The solvers are subdivide according to the physics they address.
• The utilities are also subdivided in a similar way.
35 36

Applications/utilities in OpenFOAM® Roadmap


• 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:
1. OpenFOAM® brief overview
• icoFOAM: laminar incompressible unsteady solver. 2. OpenFOAM® directory organization
• simpleFOAM: incompressible steady solver for laminar/turbulent flows.
3. Directory structure of an application/utility
• pimpleFOAM: incompressible unsteady solver for laminar/turbulent flows.
• rhoSimpleFoam: compressible steady solver for laminar/turbulent flows.
4. Applications/utilities in OpenFOAM®
• sonicFoam: unsteady compressible solver for high-speed flows (laminar/turbulent flows). 5. Directory structure of an OpenFOAM® case
• interFoam: unsteady multiphase solver for separated flows using the VOF method
(laminar and turbulent flows).
6. Running my first OpenFOAM® case setup blindfold
• laplacianFoam: Laplace equation solver. 7. A deeper view to my first OpenFOAM® case setup
• potentialFoam: potential flow solver.
8. 3D Dam break – Free surface flow
• scalarTransportFoam: steady/unsteady general transport equation solver.
• Take your time and explore the source code. 9. Flow past a cylinder – From laminar to turbulent flow
• 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. 37 38
Directory structure of an OpenFOAM® case Directory structure of an OpenFOAM® case
Directory structure of a general case Directory structure of a general case
case_name • OpenFOAM® uses a very particular directory case_name case_name: the name of the case is given by the user
├── 0 structure for running cases. ├── 0 (do not use white spaces or strange symbols). This is
│ ├── p │ ├── p the top-level directory, where you run the applications
• You should always follow the directory structure,
and utilities.
│ └── U otherwise, OpenFOAM® will complain. │ └── U
system: contains run-time control and solver
├── constant • To keep everything in order, the case directory is ├── constant numerics.
│ ├── polyMesh often located in the path │ ├── polyMesh
$WM_PROJECT_USER_DIR/run. constant: contains physical properties,
│ │ ├── boundary │ │ ├── boundary turbulence modeling properties, advanced physics
│ │ ├── faces • This is not compulsory but highly advisable. You can │ │ ├── faces and so on.
copy the case files anywhere you want.
│ │ ├── neighbour │ │ ├── neighbour constant/polyMesh: contains the
• The name of the case is given by the user (do not
│ │ ├── owner use white spaces or strange symbols).
│ │ ├── owner polyhedral mesh information.
│ │ └── points │ │ └── points 0: contains boundary conditions (BC) and initial
• Depending of the solver or application you would like
│ └── transportProperties to use, you will need different files in each sub- │ └── transportProperties conditions (IC).
├── system directory. ├── system time_directories: contains the solution and
│ ├── controlDict • Remember, you always run the applications and │ ├── controlDict derived fields. These directories are created by the
solver automatically and according to the preset
│ ├── fvSchemes utilities in the top level of the case directory (the │ ├── fvSchemes
saving frequency, e.g., 1, 2, 3, 4, … , 100.
│ └── fvSolution directory with the name case_name). Not in the │ └── fvSolution
directory system, not in the directory constant, not
└── time_directories in the directory 0. └── time_directories

39 40

Roadmap Running my first OpenFOAM® case setup blindfold


Before we start – Always remember the directory structure
1. OpenFOAM® brief overview case_name
2. OpenFOAM® directory organization ├── 0
├── constant
3. Directory structure of an application/utility │ └── polyMesh
4. Applications/utilities in OpenFOAM® ├── system
└── time_directories
5. Directory structure of an OpenFOAM® case
• To keep everything in order, the case directory is often located in the path
6. Running my first OpenFOAM® case setup blindfold $WM_PROJECT_USER_DIR/run.
• This is not compulsory but highly advisable, you can put the case in any directory of your preference.
7. A deeper view to my first OpenFOAM® case setup
• The name of the case directory if given by the user (do not use white spaces).
8. 3D Dam break – Free surface flow • You run the applications and utilities in the top level of this directory.

9. Flow past a cylinder – From laminar to turbulent flow • 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).
41 42
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Before we start – Setting OpenFOAM® cases Flow in a lid-driven square cavity – Re = 100
Incompressible flow
• As you will see, it is quite difficult to remember all the dictionary files needed to run
each application.
Physical and numerical side of the
• It is even more difficult to recall the compulsory and optional entries of each input file. problem:
• When setting a case from scratch in OpenFOAM®, what you need to do is find a • The governing equations of the problem are the
tutorial or a case that close enough does what you want to do and then you can adapt incompressible laminar Navier-Stokes equations.
it to your physics. • We are going to work in a 2D domain but the
problem can be extended to 3D easily.
• Having this in mind, you have two sources of information: • To find the numerical solution we need to
• $WM_PROJECT_DIR/tutorials discretize the domain (mesh generation), set the
(The tutorials distributed with OpenFOAM®) boundary and initial conditions, define the flow
properties, setup the numerical scheme and solver
• $PTOFC settings, and set runtime parameters (time step,
(The tutorials used during this training) simulation time, saving frequency and so on).

• If you use a GUI, things are much easier. However, OpenFOAM® does not come • For convenience, when dealing with
incompressible flows we will use relative pressure.
with a native GUI interface.
• All the dictionaries files have been already preset.
• We are going to do things in the hard way (and maybe the smart way), we are going
to use the Linux terminal
43 44

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Workflow of the case At the end of the day, you should get something like this

blockMesh

Mesh (very coarse and 2D)


icoFoam functionObjects

sampling paraview

Pressure field (relative pressure) Velocity magnitude field


45 46
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
At the end of the day, you should get something like this
Y centerline
• Let us run our first case. Go to the directory:
• And as CFD is not only about pretty colors, we should also
validate the results
X centerline

$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.
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) 47 48

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Loading OpenFOAM® environment 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
• If you are using the lab workstations, you will need to source OpenFOAM® (load and run solvers and utilities in OpenFOAM®.
OpenFOAM® environment). • 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
• To source OpenFOAM®, type in the terminal: this we use the utility checkMesh. Later on, we are going to talk about what is a good mesh.

• $> of6 • 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.
• To use PyFoam (a plotting utility) you will need to source it. Type in the terminal: • And we will finish with some quantitative post-processing and qualitative visualization using
paraFoam and OpenFOAM® utilities.
• $> anaconda3
• 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
• Remember, every time you open a new terminal window you need to source the simulation, we will talk about this later on.
OpenFOAM® and PyFoam. • 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.
• Also, you might need to load OpenFOAM® again after loading PyFoam.
• Therefore, is better to use pisoFoam or pimpleFoam which are equivalent to icoFoam but
• By default, when installing OpenFOAM® and PyFoam you do not need to do this. with many more features.
This is our choice as we have many things installed and we want to avoid conflicts
between applications.
49 50
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Running the case blindfold Running the case blindfold
• Let us run this case blindfold. • In step 1 we go to the case directory. Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
• Later we will study in details each file and directory.
• In step 2 we just list the directory structure (this step is optional). Does it look familiar to you? In
• Remember, the variable $PTOFC is pointing to the path where you unpacked the the directory 0 you will the initial and boundary conditions, in the constant directory you will
tutorials. 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.
• You can create this environment variable or write down the path to the directory.
• In step 3 we generate the mesh.
• In the terminal window type:
• In step 4 we check the mesh quality. We are going to address how to assess mesh quality later
1. $> cd $PTOFC/101OF/cavity on.
• In step 5 we run the simulation. This will show a lot information on the screen, the standard
2. $> ls –l
output stream will not be saved.
3. $> blockMesh • In step 6 we use the utility postProcess to do some sampling only of the last saved solution
$> checkMesh (the latestTime flag). This utility will read the dictionary file named sampleDict located in
4.
the directory system.
5. $> icoFoam
• In step 7 we use a gnuplot script to plot the sampled values. Feel free to take a look and reuse
6. $> postProcess -func sampleDict -latestTime this script.

$> gnuplot gnuplot/gnuplot_script • Finally, in step 8 we visualize the solution using paraFoam. In the next slides we are going to
7.
briefly explore this application.
8. $> paraFoam
51 52

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam Crash introduction to paraFoam – Toolbars
• Main Controls
Menu Bar
Toolbars
• VCR Controls (animation controls)

• Current Time Controls


Pipeline Browser
• Active Variable Controls

Properties panel • Representation Toolbar

Apply button
Press this button to • Camera Controls (view orientation)
load the case or to
apply a filter
• Center Axes Controls

• Common Filters
3D View/Canvas
Advanced Toggle • Data Analysis Toolbar
53 54
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Mesh visualization Crash introduction to paraFoam – 3D View and mouse interaction
Select Surface With Edges in the Representation Toolbar Fit to screen Select the -Z view
Select view orientation in the Camera Controls

Select Solid Color in the


Active Variable Controls Mouse interaction in the
3D view

Click on the eyeball in


the Pipeline Browser to
hide/unhide the object
Rotate

Zoom

Select mesh parts to visualize.


Pan
By default it will automatically
select internalMesh

Zoom
Select the volume fields to
visualize. By default it will select
U and p
3D View/Canvas

55 56

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Fields visualization Crash introduction to paraFoam – Filters
Select Last Frame in the VCR Controls Current Time Controls
• Filters are functions that generate, extract or derive features from the input data.
• They are attached to the input data.
Select U in Active Variable Controls
• You can access the most commonly used filters from the Common Filters toolbar

Turn on/off color bar

Select Surface in the • You can access all the filters from the menu Filter.
Representation Toolbar

Select Magnitude in the


drop down menu

Select volume fields to visualize.


By default it will select U and p.

57 58
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Filters Crash introduction to paraFoam – Slice filter

1. Select the Slice filter

Filters are attached


to the input data
If you want to erase a filter,
right click on it and select
Delete

4. Press Apply

• Even if the case is 2D, it will be 3. Optional - Turn off the


visualized as if it were a 3D case. option Show Plane

• Notice that there is only one cell in


the Z direction.
• Let us use the slice filter. This filter
will create a cut plane.
• Let us create a slice normal to the
2. Select the direction Z Normal.
Z direction. Additionally you can choose the
origin of the plane (by default is the
mid section)

59 60

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Glyph filter Crash introduction to paraFoam – Plot Over Line filter
4. Color the colors using Solid Color 1.a. Select the Plot Over Line
1. Select the Glyph filter. This filter.
filter will be applied on the
Slice1 filter
1.b. Alternative, you can select Plot
Over Line filter from the Data
Analysis Toolbar

Notice that the filter (0.5, 1, 1)


Glyph was applied on
the Slice1 filter.
Notice that we are using the filter in
a clean Pipeline

3. Press Apply

3. Press Apply

2. Filter options

Notice that the vectors are plotted in the


cell vertices. To plot the vectors at the (0.5, 0, 1)
cell centers, use the filter cell 2. Enter the coordinates of the line
centers and replot the vectors.

Line

61 62
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Filters Running the case blindfold with log files
4. Optional – Use the VCR Control to change the frame.
The line chart view will be updated automatically • In the previous case, we ran the simulation but we did not save the standard output
stream (stdout) in a log file.

• We just saw the information on-the-fly.


3. Optional - To save the
sampled data in CSV • Our advice is to always save the standard output stream (stdout) in a log file.
format, click on the filter.
Then click on the File
menu and select the • It is of interest to always save the log as if something goes wrong and you would like
option Save Data
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.
2. Select the variables to
plot in the line chart view • We might also ask for the standard error stream (stderr).

1. Click on the line chart view (the blue frame indicates that it is the active view)

63 64

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files Running the case blindfold with log files
• There are many ways to save the 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.
• From now on, we will use the Linux tee command to save log files.
• In step 2, we generate the mesh using the meshing tool blockMesh. We also redirect the
• To save a log file of the simulation or the output of any utility, you can proceed as standard output to an ascii file with the name log.blockMesh (it can be any name). The tee
follows: command will redirect the screen output to the file log.blockMesh and at the same time will
show you the information on the screen.
1. $> foamCleanTutorials • 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).
2. $> blockMesh | tee log.blockMesh
• In step 4 we run the simulation. We also redirect the standard output to an ascii file with the
3. $> checkMesh | tee log.checkMesh 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
4. $> icoFoam | tee log.icoFoam
the screen.
• To postprocess the information contained in the solver log file log.icoFoam, we can use the
utility foamLog. Type in the terminal:
The vertical bar or pipelining operator is used to concatenate commands
• $> foamLog log.icoFoam
• This utility will extract the information inside the file log.icoFoam. The extracted information is
• You can use your favorite text editor to read the log file (e.g., gedit, vi, emacs). 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:
65 • $> gnuplot 66
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files Running the case blindfold with log files
• To plot the information extracted with foamLog using gnuplot, we can proceed as • The output of step 3 is the following:
follows (remember, at this point we are using the gnuplot prompt):
1. gnuplot> set logscale y
Set log scale in the y axis

2. gnuplot> plot ‘logs/p_0’ using 1:2 with lines


Plot the file p_0 located in the directory logs, use columns 1 and 2 in the file p_0, use lines to output the plot.

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

5. gnuplot> plot ‘logs/CourantMax_0’ u 1:2 w l


To plot file CourantMax_0. The letter u is equivalent to using. The letters w l are equivalent to with lines

6. gnuplot> set logscale y

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 • 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.
67 68

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Running the case blindfold with log files and plotting the residuals Running the case blindfold with log files and plotting the residuals
• It is also possible to plot the log information on the fly. • This is a screenshot on my computer. In this case, pyFoamPlotRunner is plotting
• The easiest way to do this is by using PyFoam (you will need to install it): the initial residuals and continuity errors on the fly.
• $> 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.

69 70
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Stopping the simulation Stopping the simulation
• Your simulation will automatically stop at the time value you set using the keyword endTime in • If you want to stop the simulation and save the solution, in the controlDict dictionary made
the controlDict dictionary. the following modification,
endTime 50; stopAt writeNow;
• If for any reason you want to stop your simulation before reaching the value set by the keyword This will stop your simulation and will save the current time-step or iteration.
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 1 /*--------------------------------*- C++ -*----------------------------------*\
iteration, so be careful. 2
3
| =========
| \\ / F ield
|
| OpenFOAM: The Open Source CFD Toolbox
|
|
4 | \\ / O peration | Version: 6.x |
1 /*--------------------------------*- C++ -*----------------------------------*\ 5 | \\ / A nd | Web: www.OpenFOAM.org |
2 | ========= | | 6 | \\/ M anipulation | |
3 | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | 7 \*---------------------------------------------------------------------------*/
4 | \\ / O peration | Version: 6.x | 8 FoamFile
5 | \\ / A nd | Web: www.OpenFOAM.org | 9 {
6 | \\/ M anipulation | | 10 version 2.0;
7 \*---------------------------------------------------------------------------*/ 11 format ascii;
8 FoamFile 12 class dictionary;
9 { 13 object controlDict;
10 version 2.0; 14 }
11 format ascii; 15 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
12 class dictionary; 16
13 object controlDict; 17 application icoFoam;
14 } 18
15 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 19 startFrom startTime;
16 20
17 application icoFoam; 21 startTime 0;
18 22
19 startFrom startTime; 23 stopAt writeNow;
20 24
21 startTime 0; 25 endTime 50;
22
23 stopAt endTime;
24
25 endTime 50;
71 72

Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Stopping the simulation Stopping the simulation
• The previous modifications can be done on-the-fly, but you will need to set the • 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
keyword runTimeModifiable to true in the controlDict dictionary.
be careful.
• By setting the keyword runTimeModifiable to true, you will be able to modify most of • If you launched the solver in background, just identify the process id using top or htop (or any other process
the dictionaries on-the-fly. 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.
1 /*--------------------------------*- C++ -*----------------------------------*\
2 | ========= | |
3 | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
4 | \\ / O peration | Version: 6.x | /*---------------------------------------------------------------------------*\
5 | \\ / A nd | Web: www.OpenFOAM.org |
6 | \\/ M anipulation | |
| ========= | |
7 \*---------------------------------------------------------------------------*/ | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
8 FoamFile | \\ / O peration | Version: 6.x |
9 { | \\ / A nd | Web: www.OpenFOAM.org |
10 version 2.0; | \\/ M anipulation | |
11 format ascii;
12 class dictionary;
\*---------------------------------------------------------------------------*/
13 object controlDict; Build : 4.x-e964d879e2b3
14 } Exec : icoFoam
Date : Mar 11 2017
44 Time : 23:21:50
45 runTimeModifiable true; Host : "linux-ifxc"
46
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

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

73 74
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Stopping the simulation Cleaning the case folder
• When working locally, we usually proceed in this way: • If you want to erase the mesh and the solution in the current case folder, you can type in the
terminal,
$> foamCleanTutorials
• $> icoFoam | tee log.icofoam

This will run the solver icoFoam (by the way, this works for any solver or utility), it will save the If you are running in parallel, this will also erase the processorN directories. We will talk about
standard output stream in the file log.icofoam and will show the solver output on the fly. running in parallel later.

• If you are looking to only erase the mesh, you can type in the terminal,
• 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. $> foamCleanPolyMesh

• If we are interested in saving the last time step, we modify the controlDict dictionary and • If you are only interested in erasing the saved solutions, in the terminal type,
add the following keyword $> foamListTimes -rm
stopAt writeNow;

• If you are running in parallel and you want to erase the solution saved in the processorN
• Remember, this modification can be done on the fly. However, you will need to set the keyword directories, type in the terminal,
runTimeModifiable to yes in the controlDict dictionary. $> foamListTimes –rm -processor
75 76

Roadmap 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
1. OpenFOAM® brief overview system. After running icoFoam it also contains the time step directories 1, 2, 3,
2. OpenFOAM® directory organization ..., 48, 49, 50, the post-processing directory postProcessing, and the
log.icoFoam file (if you chose to redirect the standard output stream).
3. Directory structure of an application/utility
• The time step directories contain the values of all the variables at those time
4. Applications/utilities in OpenFOAM® steps (the solution). The 0 directory is thus the initial condition and boundary
conditions.
5. Directory structure of an OpenFOAM® case
• The constant directory contains the mesh and dictionaries for thermophysical,
6. Running my first OpenFOAM® case setup blindfold turbulence models and advanced physical models.
7. A deeper view to my first OpenFOAM® case setup • The system directory contains settings for the run, discretization schemes and
solution procedures.
8. 3D Dam break – Free surface flow
• The postProcessing directory contains the information related to the
9. Flow past a cylinder – From laminar to turbulent flow functionObjects (we are going to address functionObjects later).
• The icoFoam solver reads these files and runs the case according to those
settings.

77 78
A deeper view to my first OpenFOAM® case setup 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.
Let us explore the case directory
1 /*--------------------------------*- C++ -*----------------------------------*\
2 | ========= | |
3 | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
4 | \\ / O peration | Version: 6.x |
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 }

79 80

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant directory
(and by the way, open each file and go thru its content) Dimensions in OpenFOAM® (metric system)

No. Property Unit Symbol


• In this directory you will find the sub-directory polyMesh and the dictionary file
transportProperties. 1 Mass Kilogram kg

• The transportProperties file is a dictionary for the dimensioned scalar nu, or the 2 Length meters m
kinematic viscosity.
3 Time second s

17 nu nu [ 0 2 -1 0 0 0 0 ] 0.01; //Re 100 4 Temperature Kelvin K


18 //nu nu [ 0 2 -1 0 0 0 0 ] 0.001; //Re 1000
5 Quantity moles mol

• Notice that line 18 is commented. 6 Current ampere A

• The values between square bracket are the units. 7 Luminuous intensity candela cd

• OpenFOAM® is fully dimensional. You need to define the dimensions for


each field dictionary and physical properties defined. [ 1 (kg), 2 (m), 3 (s), 4 (K), 5 (mol), 6 (A), 7 (cd)]
• Your dimensions shall be consistent.
81 82
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant directory The constant directory
(and by the way, open each file and go thru its content) (and by the way, open each file and go thru its content)

• Therefore, the dimensioned scalar nu or the kinematic viscosity, • In this case, as we are working with an incompressible flow, we only need to define
the kinematic viscosity.

17 nu nu [ 0 2 -1 0 0 0 0 ] 0.01;

• Later on, we will ask you to change the Reynolds number, to do so you can change
the value of nu. Remember,
has the following units

[ 0 m^2 s^-1 0 0 0 0 ]

Which is equivalent to
• You can also change the free stream velocity U or the reference length L.
83 84

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant directory The constant/polyMesh directory
(and by the way, open each file and go thru its content) (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 • In this case, the polyMesh directory is initially empty. After generating the mesh, it
variables in the dictionary transportProperties. will contain the mesh in OpenFOAM® format.
• For instance, for a multiphase case you will need to define the density rho and • To generate the mesh in this case, we use the utility blockMesh. This utility reads
kinematic viscosity nu for each single phase. You will also need to define the surface the dictionary blockMeshDict located in the system folder.
tension .
• We will briefly address a few important inputs of the blockMeshDict dictionary.
• Also, depending of your physical model, you will find more dictionaries in the constant
• Do not worry, we are going to revisit this dictionary during the meshing session.
directory.
• For example, if you need to set gravity, you will need to create the dictionary g. • However, have in mind that rarely you will use this utility to generate a mesh for
complex geometries.
• If you work with compressible flows you will need to define the dynamic viscosity mu,
• Go to the directory system and open blockMeshDict dictionary with your favorite
and many other physical properties in the dictionary thermophysicalProperties.
text editor, we will use gedit.
• As we are not dealing with compressible flows (for the moment), we are not going into
details.

85 86
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The system/blockMeshDict dictionary The system/blockMeshDict dictionary
• The blockMeshDict dictionary first defines a list with a number of vertices: • The blockMeshDict dictionary also defines the boundary patches:
• The keyword convertToMeters (line 17), is a scaling factor. In this case
17 convertToMeters 1;
18
we do not scale the dimensions. • In the section boundary, we define all the surface
71 boundary
19 xmin 0;
• In the section vertices (lines 37-58), we define the vertices coordinates of 72 (
patches where we want to apply boundary conditions.
20 xmax 1;
73 movingWall Name
21 ymin 0; the geometry. In this case, there are eight vertices defining the geometry. 74 { • This step is of paramount importance, because if we do
22 ymax 1;
OpenFOAM® always uses 3D meshes, even if the simulation is 2D. 75 type wall; Type
23 zmin 0;
76 faces not define the surface patches we will not be able to
24 zmax 1;
25 • We can directly define the vertex coordinates in the section vertices 77 (
Connectivity
apply the boundary conditions.
78 (3 7 6 2)
26 xcells 20; (commented lines 49-56), or we can use macro syntax. 79 );
27 ycells 20;
80 } • For example:
28 zcells 1; • Using macro syntax we first define a variable and its value (lines 19-24), 81 fixedWalls
29
37 vertices and then we can use them by adding the symbol $ to the variable name 82 { • In line 73 we define the patch name movingWall
83 type wall;
38 ( (lines 39-46). 84 faces (the name is given by the user).
39 ($xmin $ymin $zmin) //vertex 0
85 (
40 ($xmax $ymin $zmin) //vertex 1 • In lines 26-28, we define a set of variables that will be used at a later time. 86 (0 4 7 3) • In line 75 we give a base type to the surface patch.
41 ($xmax $ymax $zmin) //vertex 2
42 ($xmin $ymax $zmin) //vertex 3 These variables are related to the number of cells in each direction. 87 (2 6 5 1)
43 ($xmin $ymin $zmax) //vertex 4 88 (1 5 4 0) In this case wall (do not worry we are going to talk
44 ($xmax $ymin $zmax) //vertex 5 • Finally, notice that the vertex numbering starts from 0 (as the counters in 89 );
about this later on).
45 ($xmax $ymax $zmax) //vertex 6 90 }
c++). This numbering applies for blocks as well. 91 frontAndBack
46
47
($xmin $ymax $zmax) //vertex 7
92 { • In line 78 we give the connectivity list of the
93 type empty;
48 /*
94 faces
vertices that made up the surface patch or face,
49 (0 0 0)
50 (1 0 0) 95 ( that is, (3 7 6 2). Have in mind that the vertices
51 (1 1 0) 96 (0 3 2 1)
52 (0 1 0) 97 (4 5 6 7) need to be neighbors and it does not matter if the
98 );
53 (0 0 0.1)
99 }
ordering is clockwise or counter clockwise.
54 (1 0 0.1)
100 );
55
56
(1
(0
1
1
0.1)
0.1)
• Remember, faces are defined by a list of 4 vertex
57 */ numbers, e.g., (3 7 6 2).
58 );

87 88

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The system/blockMeshDict dictionary The system/blockMeshDict dictionary

• To sum up, the blockMeshDict dictionary generates in this case a single block with: • As you can see, the blockMeshDict dictionary can be really tricky.
• X/Y/Z dimensions: 1.0/1.0/1.0 • If you deal with really easy geometries (rectangles, cylinders, and so on), then you
can use blockMesh to do the meshing, but this is the exception rather than the rule.
• Cells in the X, Y and Z directions: 20 x 20 x 1 cells.
• When using snappyHexMesh, (a body fitted mesher that comes with OpenFOAM®)
• One single hex block with straight lines. you will need to generate a background mesh using blockMesh. We are going to
• Patch type wall and patch name fixedWalls at three sides. deal with this later on.

• Patch type wall and patch name movingWall at one side. • Our best advice is to create a template and reuse it.
• Patch type empty and patch name frontAndBack patch at two sides. • Also, take advantage of macro syntax for parametrization, and #calc syntax to
perform inline calculations (lines 30-35 in the blockMeshDict dictionary we just
studied).
• If you are interested in visualizing the actual block topology, you can use paraFoam • We are going to deal with #codeStream syntax and #calc syntax during the
as follows, programming session.
• $> paraFoam –block

89 90
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary

• First of all, this file is automatically generated after you create the mesh • In this case, the file boundary is divided as follows
using blockMesh or snappyHexMesh, or when you convert the mesh from
18 3 Number of surface patches
a third-party format. 19 (
20 movingWall
In the list bellow there must be 3 patches
• In this file, the geometrical information related to the base type patch of 21
22
{
type wall;
definition.
23 inGroups 1(wall);
each boundary (or surface patch) of the domain is specified. 24 nFaces 20;
movingWall
25 startFace 760;
• The base type boundary condition is the actual surface patch where we are 26
27
}
fixedWalls
frontAndBack
28 {
going to apply a numerical type boundary condition (or numerical boundary 29 type wall;
30 inGroups 1(wall);
condition). 31 nFaces 60;
32 startFace 780;
• The numerical type boundary condition assign a field value to the surface 33 }

fixedWall
fixedWall
34 frontAndBack
35 {
patch (base type). 36 type empty;
37 inGroups 1(empty);
• We define the numerical type patch (or the value of the boundary 38
39
nFaces
startFace
800;
840;
condition), in the directory 0 or time directories. 40
41 )
}

frontAndBack

fixedWall

91 92

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary

• In this case, the file boundary is divided as follows • In this case, the file boundary is divided as follows

18 3 18 3 inGroups keyword
19 ( Name and type of the surface patches 19 ( • This keyword is optional. You can erase this information safely.
20 movingWall Name 20 movingWall
21 { 21 { • It is used to group patches during visualization in
22 type wall; Type • The name and type of the patch is given by 22 type wall; ParaView/paraFoam. If you open this mesh in paraFoam you will
23 inGroups 1(wall); 23 inGroups 1(wall); see that there are two groups, namely: wall and empty.
24 nFaces 20; the user. 24 nFaces 20;
25 startFace 760; 25 startFace 760; • As usual, you can change the name.
26 } • In this case the name and type was assigned 26 } • If you want to put a surface patch in two groups, you can proceed
27 fixedWalls in the dictionary blockMeshDict. 27 fixedWalls
as follows:
28 { 28 {
29 type wall; • You can change the name if you do not like it. 29 type wall; 2(wall wall1)
30 inGroups 1(wall); 30 inGroups 1(wall);
31 nFaces 60; Do not use strange symbols or white spaces. 31 nFaces 60;
In this case the surface patch belongs to the groups wall and
32 startFace 780; 32 startFace 780; wall1.
33 } • You can also change the base type. For 33 } • Groups can have more than one patch.
34 frontAndBack instance, you can change the type of the 34 frontAndBack
35 { 35 {
36 type empty;
patch movingWall from wall to patch. 36 type empty; nFaces and startFace keywords
37 inGroups 1(empty); 37 inGroups 1(empty);
38 nFaces 800;
• When converting the mesh from a third party 38 nFaces 800; • Unless you know what you are doing, you do not need to
39 startFace 840; format, OpenFOAM® will try to recover the 39 startFace 840; modify this information.
40 } information from the original format. But it 40 }
41 ) 41 ) • This information is related to the starting face and ending face of
might happen that it does not recognizes the the boundary patch in the mesh data structure.
base type and name of the original file. In this • This information is created automatically when generating the
case you will need to modify this file manually. mesh or converting the mesh.

93 94
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary
• There are a few base type patches that are constrained or paired. This means that the type • The following base type boundary conditions are constrained or paired.
should be the same in the boundary file and in the numerical boundary condition defined in the
That is, the type needs to be same in the boundary dictionary and field
field files, e.g., the files 0/U and 0/p.
variables dictionaries (e.g. U, 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), constant/polyMesh/boundary 0/U - 0/p (IC/BC)
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
symmetry symmetry
the patches is set as you would like.
symmetryPlane symmetryPlane
• 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 empty empty
(the patch type defined in the field files contained in the directory 0 (or whatever time directory
wedge wedge
you defined the boundary and initial conditions).
cyclic cyclic
• If the base type and numerical type boundary conditions are not consistent, OpenFOAM® will
complain. processor processor
• Do not worry, we are going to address boundary conditions later on.

95 96

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary

• The base type patch can be any of the numerical or derived type • The wall base type boundary condition is defined as follows:
boundary conditions available in OpenFOAM®. Mathematically speaking;
they can be Dirichlet, Neumann or Robin boundary conditions.
constant/polyMesh/boundary 0/U (IC/BC) 0/p (IC/BC)
constant/polyMesh/boundary 0/U - 0/p (IC/BC)

type fixedValue;
wall zeroGradient
fixedValue value uniform (U V W);

zeroGradient
inletOutlet
slip
patch
totalPressure
• This boundary condition is not contained in the patch base type boundary
condition group, because specialize modeling options can be used on this
supersonicFreeStream
boundary condition.
and so on …
Refer to the doxygen documentation for a list of all numerical • An example is turbulence modeling, where turbulence can be generated or
type boundary conditions available.
dissipated at the walls.
97 98
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The constant/polyMesh/boundary dictionary The system directory
(and by the way, open each file and go thru its content)
• The name of the base type boundary condition and the name of the
• The system directory consists of the following compulsory dictionary files:
numerical type boundary condition needs to be the same, if not,
• controlDict
OpenFOAM® will complain.
• fvSchemes
• Pay attention to this, specially if you are converting the mesh from another • fvSolution
format. • controlDict contains general instructions on how to run the case.
• fvSchemes contains instructions for the discretization schemes that will be used for the
different terms in the equations.
constant/polyMesh/boundary 0/U (IC/BC) 0/p (IC/BC) • fvSolution contains instructions on how to solve each discretized linear equation system.
• Do not worry, we are going to study in details the most important entries of each dictionary (the
compulsory entries).
movingWall movingWall movingWall • If you forget a compulsory keyword or give a wrong entry to the keyword, OpenFOAM® will
fixedWalls fixedWalls fixedWalls complain and it will let you what are you missing. This applies for all the dictionaries in the
hierarchy of the case directory.
frontAndBack frontAndBack frontAndBack
• There are many optional parameters, to know all of them refer to the doxygen documentation or
the source code. Hereafter we will try to introduce a few of them.
• OpenFOAM® will not complain if you are not using optional parameters, after all, they are
• As you can see, all the names are the same across all the dictionary files. optional. However, if the entry you use for the optional parameter is wrong OpenFOAM® will let
you know.
99 100

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The controlDict dictionary The controlDict dictionary
• The controlDict dictionary contains runtime simulation controls, such • So how do we know what options are available for each keyword?
as, start time, end time, time step, saving frequency and so on. • The hard way is to refer to the source code.
• Most of the entries are self-explanatory. • The easy way is to use the banana method.
17 application icoFoam; 17 application icoFoam;
18 18 • So what is the banana method? This method consist in inserting a dummy word
19 startFrom startTime; • This case starts from time 0 (keyword startFrom – line 19 – and 19 startFrom startTime;
(that does not exist in the installation) and let OpenFOAM® list the available
20 20
21 startTime 0; keyword startTime – line 21 –). If you have the initial solution in a 21 startTime 0; options.
22 different time directory, just enter the number in line 21. 22
• For example. If you add banana in line 23, you will get this output:
23 stopAt endTime; 23 stopAt banana;
24
25 endTime 50;
• The case will stop when it reaches the desired time set using the keyword 24
25 endTime 50;
banana is not in enumeration
26 stopAt (line 23). 26 4
27 deltaT 0.01; 27 deltaT 0.01;
28 • It will run up to 50 seconds (keyword endTime – line 25 –). 28 (
29 writeControl runTime; 29 writeControl runTime;
30 30 nextWrite
31 writeInterval 1; • The time step of the simulation is 0.01 seconds (keyword deltaT 31 writeInterval 1;
32 – line 27 –). 32 writeNow
33 purgeWrite 0; 33 purgeWrite 0;
noWriteNow
34
35 writeFormat ascii;
• It will write the solution every second (keyword writeInterval – line 31 –) 34
35 writeFormat ascii; endTime
36 of simulation time (keyword runTime – line 29 –). 36
37 writePrecision 8; 37 writePrecision 8; )
38 • It will keep all the solution directories (keyword purgeWrite – line 33 –). 38
• So your options are nextWrite, writeNow, noWriteNow, endTime
39 writeCompression off; 39 writeCompression off;
40 If you want to keep only the last 5 solutions just change the value to 5. 40
41 timeFormat general; 41 timeFormat general; • And how do we know that banana does not exist in the source code? Just type in
42 • It will save the solution in ascii format (keyword writeFormat – line 35 –) 42 the terminal:
43 timePrecision 6; 43 timePrecision 6;
44
with a precision of 8 digits (keyword writePrecision – line 37 –). 44 • $> src
45 runTimeModifiable true; 45 runTimeModifiable true;
• And as the option runTimeModifiable (line 45) is on (true), we can • $> grep –r –n banana .
modify all these entries while we are running the simulation. • If you see some bananas in your output someone is messing around with your
installation.
• FYI, you can modify the entries on-the-fly for most of the dictionaries files.
• Remember, you can use any dummy word, but you have to be sure that it does
not exist in OpenFOAM®.
101 102
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The controlDict dictionary The fvSchemes dictionary

• The fvSchemes dictionary contains the information related to


• If you forget a compulsory keyword, OpenFOAM® will tell you what 17 ddtSchemes the discretization schemes for the different terms appearing in
17 application icoFoam; are you missing. 18 {
18 19 default backward;
the governing equations.
19 startFrom startTime;
20 • So if you comment line 25, you will get this output: 20
21
}
• As for the controlDict dictionary, the parameters can be
21 startTime 0; 22 gradSchemes
22 23 {
changed on-the-fly.
23 stopAt endTime; 24 default Gauss linear;
24 --> FOAM FATAL IO ERROR 25 grad(p) Gauss linear; • Also, if you want to know what options are available, just use
25 //endTime 50; 26 }
26 keyword endTime is undefined in dictionary … 27
the banana method.
27 deltaT 0.01; 28 divSchemes
28 29 { • In this case we are using the backward method for time
29 writeControl runTime; 30 default none;
30 • This output is just telling you that you are missing the keyword 31 div(phi,U) Gauss linear;
discretization (ddtSchemes). For gradients discretization
31 writeInterval 1;
32 endTime.
32 } (gradSchemes) we are using Gauss linear method. For the
33
33 purgeWrite 0; 34 laplacianSchemes discretization of the convective terms (divSchemes) we are
34 35 {
35 writeFormat ascii; 36 default Gauss linear orthogonal;
using linear interpolation for the term div(phi,U).
36
37 writePrecision 8; • Do not pay attention to the words FATAL ERROR, maybe the 37
38
}
• For the discretization of the Laplacian (laplacianSchemes and
38
39 writeCompression off;
developers of OpenFOAM® exaggerated a little bit. 39 interpolationSchemes
snGradSchemes) we are using the Gauss linear method with
40 {
40 41 default linear; orthogonal corrections.
41 timeFormat general; 42 }
42
43 timePrecision 6;
43
44 snGradSchemes
• The method we are using is second order accurate but
44
45 runTimeModifiable true;
45 { oscillatory. We are going to talk about the properties of the
46 default orthogonal;
47 } numerical schemes later on.
• Remember, at the end of the day we want a solution that is
second order accurate.
103 104

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The fvSolution dictionary The fvSolution dictionary

17 solvers
• The fvSolution dictionary contains the instructions of how 17 solvers
• To solve U we are using the smoothSolver method, with the
18 { to solve each discretized linear equation system. The equation 18 { smoother symGaussSeidel, an absolute tolerance equal to
19 p 19 p
20 { solvers, tolerances, and algorithms are controlled from the sub- 20 { 1e-08 and a relative tolerance relTol equal to 0.
21 solver PCG; 21 solver PCG;
dictionary solvers.
22 preconditioner DIC; 22 preconditioner DIC; • The solvers will iterative until reaching any of the tolerance
23 tolerance 1e-06; 23 tolerance 1e-06;
24 relTol 0; • In the dictionary file fvSolution (and depending on the solver 24 relTol 0; values set by the user or reaching a maximum value of
39 }
you are using), you will find the additional sub-dictionaries 39 }
iterations (optional entry).
40 PISO, PIMPLE, SIMPLE, and relaxationFactors. These 40
41 pFinal 41 pFinal • FYI, solving for the velocity is relative inexpensive, whereas
42 { entries will be described later. 42 {
43 $p; 43 $p;
solving for the pressure is expensive.
44 relTol 0; • As for the controlDict and fvSchemes dictionaries, the 44 relTol 0;
45 } 45 } • The PISO sub-dictionary contains entries related to the
46 parameters can be changed on-the-fly. 46
47 U 47 U
pressure-velocity coupling method (the PISO method).
48 { • Also, if you want to know what options are available just use 48 {
49 solver smoothSolver; 49 solver smoothSolver; • In this case we are doing only one PISO correction and no
50 smoother symGaussSeidel; the banana method. 50 smoother symGaussSeidel;
51 tolerance 1e-08; 51 tolerance 1e-08;
orthogonal corrections.
52 relTol 0; • In this case, to solve the pressure (p) we are using the PCG 52 relTol 0;
53 } 53 } • You need to do at least one PISO loop (nCorrectors).
54 } method, with the preconditioner DIC, an absolute tolerance 54 }
55 55
56 PISO
equal to 1e-06 and a relative tolerance relTol equal to 0. 56 PISO
57 { 57 {
58 nCorrectors 1; • The entry pFinal refers to the final pressure correction (notice 58 nCorrectors 1;
59 nNonOrthogonalCorrectors 0; 59 nNonOrthogonalCorrectors 0;
60 pRefCell 0;
that we are using macro syntax), and we are using a relative 60 pRefCell 0;
61 pRefValue 0; tolerance relTol equal to 0. We are putting more computational 61 pRefValue 0;
62 } 62 }
effort in the last iteration.

105 106
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The system directory The sampleDict dictionary
(optional dictionary files)
Type of sampling, sets will sample along a line.
Format of the output file, raw format is a generic format
• In the system directory you will also find these two additional files: 17 type sets; that can be read by many applications. The output file is
18
19 setFormat raw;
human readable (ascii format).
• decomposeParDict 20
23 interpolationScheme cellPointFace; Interpolation method at the solution level (location of the
24
interpolation points).
• sampleDict
26 fields
27 (
28 U Fields to sample.
29 );
30
31 sets
32 (
Sample method. How to interpolate the solution to the
• decomposeParDict is read by the utility decomposePar. This dictionary
33
34 l1
35 {
sample entity (line in this case)
file contains information related to the mesh partitioning. This is used when 38
43
type
axis
lineFace;
x;
44 start ( -1 0.5 0); Location of the sample line. We define start and end
running in parallel. We will address running in parallel later. 45 end ( 2 0.5 0); point, and the axis of the sampling.
46 }
47
• sampleDict is read by the utility postProcess. This utility sample field 48
49
l2
{

data (points, lines or surfaces). In this dictionary file we specify the sample 52
57
type
axis
lineFace;
y;
Sample method from the solution to the line.
58 start (0.5 -1 0);
location and the fields to sample. The sampled data can be plotted using 59
60 }
end (0.5 2 0);

gnuplot or Python. 61
62 );
Location of the sample line. We define start and end
point, and the axis of the sampling.

107 108

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The sampleDict dictionary The 0 directory
(and by the way, open each file and go thru its content)
The sampled information is always saved in the
directory,
17 type sets; • The 0 directory contains the initial and boundary conditions for all primitive variables,
18 postProcessing/name_of_input_dictionary
19 setFormat raw; in this case p and U. The U file contains the following information (velocity vector):
20
23 interpolationScheme cellPointFace;
24
17 dimensions [0 1 -1 0 0 0 0]; Dimensions of the field
26
27
fields
(
As we are sampling the latest time solution (50) and 18
28 U using the dictionary sampleDict, the sampled data 19 internalField uniform (0 0 0);
29 );
20
30 will be located in the directory: 21 boundaryField
31 sets
22 {
32
33
(
postProcessing/sampleDict/50 23 movingWall
34 l1
24 { Uniform initial conditions.
35 {
38 type lineFace; 25 type fixedValue;
43 axis x; 26 value uniform (1 0 0); The velocity field is initialize to (0 0 0) in all
44 start ( -1 0.5 0); The files l1_U.xy and l2_U.xy located in the 27 }
45 end ( 2 0.5 0); the domain
46 } directory postProcessing/sampleDict/50 28
29 fixedWalls
47
contain the sampled data. Feel free to open them using Remember velocity is a vector with three
48 l2 30 {
49 { 31 type fixedValue; components, therefore the notation (0 0 0).
52 type lineFace;
your favorite text editor.
32 value uniform (0 0 0);
57 axis y;
58 start (0.5 -1 0); 33 }
59 end (0.5 2 0); 34
60 } 35 frontAndBack Note:
61 Name of the output file If you take some time and compare the files 0/U and
36 {
62 ); constant/polyMesh/boundary, you will see that the name and type of each
37 type empty;
numerical type patch (the patch defined in 0/U), is consistent with the base
38 } type patch (the patch defined in the file constant/polyMesh/boundary).
Name of the output file 39 }

109 110
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The 0 directory The 0 directory
(and by the way, open each file and go thru its content) (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, • 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): in this case p and U. The p file contains the following information (modified pressure):

17 dimensions [0 1 -1 0 0 0 0]; Dimensions of the field 17 dimensions [0 2 -2 0 0 0 0]; Dimensions of the field
18 18
19 internalField uniform (0 0 0); 19 internalField uniform 0;
20 20
21 boundaryField 21 boundaryField
22 { 22 {
23 movingWall 23 movingWall
24 { 24 { Uniform initial conditions.
25 type fixedValue; Numerical boundary condition for the patch 25 type zeroGradient;
26 value uniform (1 0 0); movingWall 26 } The modified pressure field is initialize to 0
27 } 27
28 28 fixedWalls
in all the domain. This is relative
29 fixedWalls 29 { pressure.
30 { 30 type zeroGradient;
31 type fixedValue; Numerical boundary condition for the patch 31 }
32 value uniform (0 0 0); fixedWalls 32
33 } 33 frontAndBack
34 34 {
35 frontAndBack 35 type empty; Note:
If you take some time and compare the files 0/p and
36 { 36 }
37 type empty;
Numerical boundary condition for the patch 37 }
constant/polyMesh/boundary, you will see that the name and type of each
numerical type patch (the patch defined in 0/p), is consistent with the base
38 } frontAndBack (this is a constrained boundary 38 type patch (the patch defined in the file constant/polyMesh/boundary).
39 } condition).
111 112

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The 0 directory
(and by the way, open each file and go thru its content) A very important remark on the pressure field

• The 0 directory contains the initial and boundary conditions for all primitive variables, • We just used icoFoam which is an incompressible solver.
in this case p and U. The p file contains the following information (modified pressure): • Let us be really loud on this. All the incompressible solvers implemented in OpenFOAM®
(icoFoam, simpleFoam, pisoFoam, and pimpleFoam), use the modified pressure, that is,
17 dimensions [0 2 -2 0 0 0 0]; Dimensions of the field
18
19 internalField uniform 0;
20 with units
21 boundaryField
22 {
23 movingWall
24 {
Numerical boundary condition for the patch • Or in OpenFOAM® jargon: dimensions [0 2 -2 0 0 0 0]
25 type zeroGradient;
26 } movingWall
27
• So when visualizing or post processing the results do not forget to multiply the pressure by
28 fixedWalls the density in order to get the right units of the physical pressure, that is,
29 {
30 type zeroGradient;
Numerical boundary condition for the patch
31 } fixedWalls
32
33 frontAndBack
34 {
35 type empty;
Numerical boundary condition for the patch
36 } frontAndBack (this is a constrained boundary • Or in OpenFOAM® jargon: dimensions [1 -1 -2 0 0 0 0]
37 } condition).
38

113 114
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
• Coming back to the headers, and specifically the headers related to the field variable • If the field variable is a vector, the class should be volVectorField.
dictionaries (e.g. U, p, gradU, and so on). /*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
• In the header of the field variables, the class type should be consistent with the type | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 6.x |
of field variable you are using. | \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
• Be careful with this, specially if you are copying and pasting files. \*---------------------------------------------------------------------------*/
FoamFile
• If the field variable is a scalar, the class should be volScalarField. {
version 2.0;
format ascii;
class volVectorField;
object U;
}
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 6.x | • If the field variable is a tensor (e.g. the velocity gradient tensor), the class should be
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | | volTensorField.
\*---------------------------------------------------------------------------*/
FoamFile /*--------------------------------*- C++ -*----------------------------------*\
{ | ========= | |
version 2.0; | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
format ascii; | \\ / O peration | Version: 6.x |
class volScalarField; | \\ / A nd | Web: www.OpenFOAM.org |
object p; | \\/ M anipulation | |
} \*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // FoamFile
{
version 2.0;
format ascii;
class volTensorField;
object gradU;
115 } 116

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The output screen The output screen
• Finally, let us talk about the output screen, which shows a lot of information. • 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 {
Velocity residuals 51 Name of the folder where the output of
Simulation time 52 /////////////////////////////////////////////////////////////////////////// the functionObject will be saved
Courant number 53
54 minmaxdomain
Pressure residuals 55 {
56 type fieldMinMax; functionObject to use
No orthogonal corrections
57
Only one PISO correction 58 functionObjectLibs ("libfieldFunctionObjects.so");
Execution time (wall time) 59
60 enabled true; //true or false Turn on/off functionObject
Continuity errors 61
62 mode component;
63
Additional information 64 writeControl timeStep;
Minimum and maximum values of each field 65 writeInterval 1; Output interval of functionObject
End of the simulation
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 };
117 118
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The output screen The output screen
• Another very important output information is the CFL or Courant number. • To control the CFL number you can change the time step or you can change the mesh.

• The Courant number imposes the CFL number condition, which is the maximum allowable • The easiest way is by changing the time step.
CFL number a numerical scheme can use. For the n - dimensional case, the CFL number • For a time step of 0.01 seconds, this is the output you should get for this case,
condition becomes,
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

fieldMinMax minmaxdomain output:


• In OpenFOAM®, most of the solvers are implicit, which means they are unconditionally min(p) = -0.37208362 at location (0.025 0.975 0.5)
max(p) = 0.77640927 at location (0.975 0.975 0.5)
min(U) = (0.00028445255 -0.00028138799 0) at location (0.025 0.025 0.5)
stable. In other words, they are not constrained to the CFL number condition. max(U) = (0.00028445255 -0.00028138799 0) at location (0.025 0.025 0.5)

• However, the fact that you are using a numerical method that is unconditionally stable, does Time = 50
CFL number at
not mean that you can choose a time step of any size. 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
• The time-step must be chosen in such a way that it resolves the time-dependent features, and it 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
maintains the solver stability. ExecutionTime = 4.47 s ClockTime = 5 s

fieldMinMax minmaxdomain output:


• For the moment and for the sake of simplicity, let us try to keep the CFL number below 5.0 and min(p) = -0.37208345 at location (0.025 0.975 0.5)
max(p) = 0.77640927 at location (0.975 0.975 0.5)
preferably close to 1.0 (for good accuracy). min(U) = (0.00028445255 -0.00028138799 0) at location (0.025 0.025 0.5)
max(U) = (0.00028445255 -0.00028138799 0) at location (0.025 0.025 0.5)

• 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. 119 120

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The output screen The output screen
• To control the CFL number you can change the time step or you can change the mesh. • 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. • 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, • For a time step of 0.5 seconds, this is the output you should get for this case,

Time = 49.9 Time = 2


CFL number at CFL number at
Courant Number mean: 0.4441161 max: 1.6798756 Courant Number mean: 1.6828931 max: 5.6061178
time step n - 1 time step n - 1
smoothSolver: Solving for Ux, Initial residual = 0.00016535808, Final residual = 2.7960145e-09, No Iterations 5 smoothSolver: Solving for Ux, Initial residual = 0.96587058, Final residual = 4.9900041e-09, No Iterations 27
smoothSolver: Solving for Uy, Initial residual = 0.00015920267, Final residual = 2.7704949e-09, No Iterations 5 smoothSolver: Solving for Uy, Initial residual = 0.88080685, Final residual = 9.7837781e-09, No Iterations 25
DICPCG: Solving for p, Initial residual = 0.0015842846, Final residual = 5.2788554e-07, No Iterations 26 DICPCG: Solving for p, Initial residual = 0.95568243, Final residual = 7.9266324e-07, No Iterations 33
time step continuity errors : sum local = 8.6128916e-09, global = 3.5439859e-19, cumulative = 2.4940081e-17 time step continuity errors : sum local = 6.3955627e-06, global = 1.3227253e-17, cumulative = 1.4125109e-17
ExecutionTime = 0.81 s ClockTime = 1 s ExecutionTime = 0.04 s ClockTime = 0 s

fieldMinMax minmaxdomain output: fieldMinMax minmaxdomain output:


min(p) = -0.34322821 at location (0.025 0.975 0.5) min(p) = -83.486425 at location (0.975 0.875 0.5) Compare these values with the values
max(p) = 0.73453489 at location (0.975 0.975 0.5) max(p) = 33.078468 at location (0.025 0.925 0.5)
of the previous cases. For the
min(U) = (0.0002505779 -0.00025371425 0) at location (0.025 0.025 0.5) min(U) = (0.1309243 -0.13648118 0) at location (0.025 0.025 0.5)
max(U) = (0.0002505779 -0.00025371425 0) at location (0.025 0.025 0.5) max(U) = (0.1309243 -0.13648118 0) at location (0.025 0.025 0.5) physics involve these values are
unphysical.
Time = 50 Time = 2.5
CFL number at Courant Number mean: 8.838997 max: 43.078153
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 #0 Foam::error::printStack(Foam::Ostream&) at ??:? time step n (way
smoothSolver: Solving for Uy, Initial residual = 0.00015720331, Final residual = 2.7354499e-09, No Iterations 5 #1 Foam::sigFpe::sigHandler(int) at ??:? too high)
DICPCG: Solving for p, Initial residual = 0.0015662416, Final residual = 5.2290439e-07, No Iterations 26 #2 ? in "/lib64/libc.so.6"
time step continuity errors : sum local = 8.5379223e-09, global = -3.6676527e-19, cumulative = 2.4573316e-17 #3 Foam::symGaussSeidelSmoother::smooth(Foam::word const&, Foam::Field<double>&, Foam::lduMatrix const&, Foam::Field<double> const&,
ExecutionTime = 0.81 s ClockTime = 1 s Foam::FieldField<Foam::Field, double> const&, Foam::UPtrList<Foam::lduInterfaceField const> const&, unsigned char, int) at ??:?
#4 Foam::symGaussSeidelSmoother::smooth(Foam::Field<double>&, Foam::Field<double> const&, unsigned char, int) const at ??:?
fieldMinMax minmaxdomain output: #5 Foam::smoothSolver::solve(Foam::Field<double>&, Foam::Field<double> const&, unsigned char) const at ??:?
min(p) = -0.34244269 at location (0.025 0.975 0.5) #6 ? at ??:?
max(p) = 0.73656831 at location (0.975 0.975 0.5)
min(U) = (0.00025028679 -0.00025338014 0) at location (0.025 0.025 0.5) The solver crashed.
max(U) = (0.00025028679 -0.00025338014 0) at location (0.025 0.025 0.5) The offender? Time step too large.

121 122
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The output screen Error output
• Another output you should monitor are the continuity errors. • If you forget a keyword or a dictionary file, give a wrong option to a compulsory or optional entry,
• These numbers should be small (it does not matter if they are negative or positive). 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.
• If these values increase in time (about the order of 1e-2), you better control the case setup because
something is wrong. • This error does not mean that the actual OpenFOAM® installation is corrupted. It is telling you
• The continuity errors are defined in the following file that you are missing something or something is wrong in a dictionary.
$WM_PROJECT_DIR/src/finiteVolume/cfdTools/incompressible/continuityErrs.H • Maybe the guys of OpenFOAM® went a little bit extreme here.

/*---------------------------------------------------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: 6.x |
Time = 50 | \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
Courant Number mean: 0.44411473 max: 1.6798833 \*---------------------------------------------------------------------------*/
smoothSolver: Solving for Ux, Initial residual = 0.00016378098, Final residual = 2.7690608e-09, No Iterations 5 Build : 5.x-5d8318b22cbe
smoothSolver: Solving for Uy, Initial residual = 0.00015720331, Final residual = 2.7354499e-09, No Iterations 5 Exec : icoFoam
DICPCG: Solving for p, Initial residual = 0.0015662416, Final residual = 5.2290439e-07, No Iterations 26 Date : Nov 02 2014
time step continuity errors : sum local = 8.5379223e-09, global = -3.6676527e-19, cumulative = 2.4573316e-17 Time : 00:33:41
ExecutionTime = 0.81 s ClockTime = 1 s Host : "linux-cfd"
PID : 3675
fieldMinMax minmaxdomain output: Case : /home/cfd/my_cases_course/cavity
min(p) = -0.34244269 at location (0.025 0.975 0.5) nProcs : 1
max(p) = 0.73656831 at location (0.975 0.975 0.5) sigFpe : Enabling floating point exception trapping (FOAM_SIGFPE).
min(U) = (0.00025028679 -0.00025338014 0) at location (0.025 0.025 0.5) fileModificationChecking : Monitoring run-time modified files using timeStampMaster
max(U) = (0.00025028679 -0.00025338014 0) at location (0.025 0.025 0.5) Continuity errors allowSystemOperations : Allowing user-supplied system call operations

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Create time

--> FOAM FATAL IO ERROR:

123 124

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Error output
• Also, before entering into panic read carefully the output screen because OpenFOAM® is telling • It is very important to read the screen and understand the output.
you what is the error and how to correct it.

Build : 6.x-5d8318b22cbe
Exec : icoFoam
Date
Time
: Nov 02 2014
: 00:33:41 “E perience is simply the name we give our mistakes.”
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
• Train yourself to identify the errors. Hereafter we list a few possible errors.
--> FOAM FATAL IO ERROR:
• Missing compulsory file p
banana_endTime is not in enumeration: The origin of the error
4
( --> FOAM FATAL IO ERROR:
endTime
nextWrite cannot find file
Possible options to correct the error
noWriteNow
writeNow file: /home/joegi/my_cases_course/6/101OF/cavity/0/p at line 0.
)

file: /home/cfd/my_cases_course/cavity/system/controlDict.stopAt at line 24. Location of the error From function regIOobject::readStream()
in file db/regIOobject/regIOobjectRead.C at line 73.
From function NamedEnum<Enum, nEnum>::read(Istream&) const
in file lnInclude/NamedEnum.C at line 72. FOAM exiting
FOAM exiting

125 126
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Error output
• Mismatching patch name in file p • Missing entry in file fvSolution at keyword PISO

--> FOAM FATAL IO ERROR: --> FOAM FATAL IO ERROR:


Cannot find patchField entry for xmovingWall "ill defined primitiveEntry starting at keyword 'PISO' on line 68 and ending at line 68"

file: /home/joegi/my_cases_course/6/101OF/cavity/0/p.boundaryField from line 25 to line 35. file: /home/joegi/my_cases_course/6/101OF/cavity/system/fvSolution at line 68.

From function GeometricField<Type, PatchField, GeoMesh>::GeometricBoundaryField::readField(const From function primitiveEntry::readEntry(const dictionary&, Istream&)
DimensionedField<Type, GeoMesh>&, const dictionary&) in file lnInclude/IOerror.C at line 132.
in file /home/joegi/OpenFOAM/OpenFOAM-6/src/OpenFOAM/lnInclude/GeometricBoundaryField.C at line 209.
FOAM exiting
FOAM exiting

• Incompatible dimensions. Likely the offender is the file U


• Missing compulsory keyword in fvSchemes --> FOAM FATAL ERROR:
incompatible dimensions for operation
[U[0 1 -2 1 0 0 0] ] + [U[0 1 -2 2 0 0 0] ]
--> FOAM FATAL IO ERROR:
keyword div(phi,U) is undefined in dictionary From function checkMethod(const fvMatrix<Type>&, const fvMatrix<Type>&)
"/home/joegi/my_cases_course/6/101OF/cavity/system/fvSchemes.divSchemes" in file /home/joegi/OpenFOAM/OpenFOAM-6/src/finiteVolume/lnInclude/fvMatrix.C at line 1295.
file: /home/joegi/my_cases_course/6/101OF/cavity/system/fvSchemes.divSchemes from line 30 to line 30. FOAM aborting
From function dictionary::lookupEntry(const word&, bool, bool) const #0 Foam::error::printStack(Foam::Ostream&) at ??:?
in file db/dictionary/dictionary.C at line 442. #1 Foam::error::abort() at ??:?
#2 void Foam::checkMethod<Foam::Vector<double> >(Foam::fvMatrix<Foam::Vector<double> > const&,
FOAM exiting 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
127 Aborted 128

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Error output
• Missing keyword deltaT in file controlDict • Unknown boundary condition type.

--> FOAM FATAL IO ERROR: --> FOAM FATAL IO ERROR:


keyword deltaT is undefined in dictionary "/home/joegi/my_cases_course/6/101OF/cavity/system/controlDict" Unknown patchField type sfixedValue for patch type wall

file: /home/joegi/my_cases_course/6/101OF/cavity/system/controlDict from line 17 to line 69. Valid patchField types are :

From function dictionary::lookupEntry(const word&, bool, bool) const 74


in file db/dictionary/dictionary.C at line 442. (
SRFFreestreamVelocity
FOAM exiting SRFVelocity
SRFWallVelocity
activeBaffleVelocity

...
• Missing file points in directory polyMesh. Likely you are missing the mesh. ...
...

--> FOAM FATAL ERROR: variableHeightFlowRateInletVelocity


Cannot find file "points" in directory "polyMesh" in times 0 down to constant waveTransmissive
wedge
From function Time::findInstance(const fileName&, const word&, const IOobject::readOption, const word&) zeroGradient
in file db/Time/findInstance.C at line 203. )

FOAM exiting
file: /home/joegi/my_cases_course/6/101OF/cavity/0/U.boundaryField.movingWall from line 25 to line 26.

From function fvPatchField<Type>::New(const fvPatch&, const DimensionedField<Type, volMesh>&, const


dictionary&)
in file /home/joegi/OpenFOAM/OpenFOAM-6/src/finiteVolume/lnInclude/fvPatchFieldNew.C at line 143.

FOAM exiting

129 130
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Error output
• This one is specially hard to spot • 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.
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | • For instance, this output is telling us that the error is due to SIGFPE and the class associated to
| \\ / O peration | Version: 6.x |
| \\ / A nd | Web: www.OpenFOAM.org | the error is lduMatrix. It is also telling you that the GAMGSolver solver is the affected one
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/ (likely the offender is the pressure).
Build : 6.x-5d8318b22cbe
Exec : icoFoam #0 Foam::error::printStack(Foam::Ostream&) at ??:?
Date : Nov 02 2014 #1 Foam::sigFpe::sigHandler(int) at ??:?
Time : 00:33:41 #2 in "/lib64/libc.so.6"
Host : "linux-cfd" #3 Foam::DICPreconditioner::calcReciprocalD(Foam::Field<double>&, Foam::lduMatrix const&) at ??:?
PID : 3675 #4 Foam::DICSmoother::DICSmoother(Foam::word const&, Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double>
fileName::stripInvalid() called for invalid fileName /home/cfd/my_cases_course/cavity0 const&, Foam::FieldField<Foam::Field, double> const&, Foam::UPtrList<Foam::lduInterfaceField const> const&) at ??:?
For debug level (= 2) > 1 this is considerd fatal #5 Foam::lduMatrix::smoother::addsymMatrixConstructorToTable<Foam::DICSmoother>::New(Foam::word const&,
Aborted 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&,
• This error is related to the name of the working directory. In this case the name of the Foam::dictionary const&) at ??:?
#7 Foam::GAMGSolver::initVcycle(Foam::PtrList<Foam::Field<double> >&, Foam::PtrList<Foam::Field<double> >&,
working directory is cavity 0 (there is a blank space between the word cavity and 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 ??:?
the number 0). #9 Foam::fvMatrix<double>::solveSegregated(Foam::dictionary const&) at ??:?
#10 Foam::fvMatrix<double>::solve(Foam::dictionary const&) at ??:?
• Do not use blank spaces or funny symbols when naming directories and files. #11
at ??:?
#12 __libc_start_main in "/lib64/libc.so.6"
• Instead of cavity 0 you could use cavity_0. #13
at /home/abuild/rpmbuild/BUILD/glibc-2.17/csu/../sysdeps/x86_64/start.S:126
131 Floating point exception 132

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Dictionary files general features Dictionary files general features

• OpenFOAM® follows same general syntax rules as in C++. • Scalars, vectors, lists and dictionaries.
• Commenting in OpenFOAM® (same as in C++): • List entries are contained within parentheses ( ). A list can contain scalars, vectors, tensors, words, and so on.

/* • A list of scalars is represented as follows:


// This is a line comment This is a block comment name_of_the_list
*/ (
0
1
• As in C++, you can use the #include directive in your dictionaries (do not forget to create the respective include file):
2
#include “ n t C nd t n ” );

• A list of vectors is represented as follows:


• Scalars, vectors, lists and dictionaries. name_of_the_list
• Scalars in OpenFOAM® are represented by a single value, e.g., (
(0 0 0)
3.14159 (1 0 0)
• Vectors in OpenFOAM® are represented as a list with three components, e.g., (2 0 0)
);
(1.0 0.0 0.0)
• A second order tensor in OpenFOAM® is represented as a list with nine components, e.g., • A list of words is represented as follows
( name_of_the_list
1.0 0.0 0.0 (
0.0 1.0 0.0 “ rd1”
0.0 0.0 1.0 “ rd2”
) “ rd3”
);
133 134
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Dictionary files general features Dictionary files general features
• OpenFOAM® uses dictionaries to specify data in an input file (dictionary file).
• Macro expansion.
• A dictionary in OpenFOAM® can contain multiple data entries and at the same time dictionaries can contain • We first declare a variable (x = 10) and then we use it through the $ macro substitution ($x).
sub-dictionaries.
• To specify a dictionary entry, the name is followed by the keyword entries in curly braces: vectorField (20 0 0); //Declare variable

solvers Dictionary solvers internalField uniform $vectorField; //Use declared variable


{
p Sub-dictionary p
{ scalarField 101328; //Declare variable
solver PCG;
preconditioner DIC; type fixedValue;
value uniform $scalarField; //Use declared variable
tolerance 1e-06;
relTol 0;
} • You can use macro expansion to duplicate and access variables in dictionaries

U Sub-dictionary U p // Declare/create the dictionary p


{ {
solver PBiCGStab; solver PCG;
preconditioner DILU; preconditioner DIC;
tolerance 1e-06; tolerance 1e-06;
relTol 0; relTol 0;
} }

… $p; //To create a copy of the dictionary p
… $p.solver; //To access the variable solver in the dictionary p
} 135 136

A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Dictionary files general features Dictionary files general features

• In tead of writing t e poor an’ way : • Inline calculations.


• You can use the directive #calc to do inline calculations, the syntax is as follows:
leftWall rightWall topWall
X = 10.0; //Declare variable
{ { {
type fixedValue; type fixedValue; type fixedValue; Y = 3.0; //Declare variable
value uniform (0 0 0); value uniform (0 0 0); value uniform (0 0 0);
} } } Z #c c “$ *$ – 12.0”; //Do inline calculation. The result is saved in the variable Z

• You can write (the lazy way):


• 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.
“( eft|r ght|t )W ”
• Switches: they are used to enable or disable a function or a feature in the dictionaries.
{
type fixedValue; • Switches are logical values. You can use the following values:
value uniform (0 0 0);
} Switches
false true
• You could also try (even lazier):
off on
“.*W ” no yes
{
type fixedValue; n y
value uniform (0 0 0); f t
}
none true

• OpenFOAM® understands the syntax of regular expressions (regex or regeaxp). • You can find all the valid switches in the following file:
137 OpenFOAM-6/src/OpenFOAM/primitives/bools/Switch/Switch.C 138
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Solvers and utilities help Solvers and utilities help
• To get more information about the boundary conditions, post-processing utilities, and the API read the
• If you need help about a solver or utility, you can use the option –help. For Doxygen documentation.
instance: • If you did not compile the Doxygen documentation, you can access the information online,
http://cpp.openfoam.org/v6/

• $> icoFoam –help


API documentation
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.

Boundary conditions and post-processing


utilities documentation

139 140

A deeper view to my first OpenFOAM® case setup Roadmap


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, 1. OpenFOAM® brief overview
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 2. OpenFOAM® directory organization
controlDict, fvSchemes and fvSolution). Did the simulation converge? Did it crash? Any comments.
• If your simulation crashed, try to solve the problem. 3. Directory structure of an application/utility
(Hint: try to reduce the time-step to get a CFL less than 1)
• Besides reducing the time-step, can you find another solution? 4. Applications/utilities in OpenFOAM®
(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 5. Directory structure of an OpenFOAM® case
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
6. Running my first OpenFOAM® case setup blindfold
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
7. A deeper view to my first OpenFOAM® case setup

scheme.
Run the simulation using Gauss upwind instead of Gauss linear for the term div(phi,U) (fvSchemes). Do
8. 3D Dam break – Free surface flow

you get the same quantitative results?
Sample the field variables U and P at a different location and plot the results using gnuplot.
9. Flow past a cylinder – From laminar to turbulent flow
• What density value do you think we were using? What about dynamic viscosity?
Hint: the physical pressure is equal to the modified pressure and

141 142
3D Dam break – Free surface flow 3D Dam break – Free surface flow

Dam break free surface flow Workflow of the case

Physical and numerical side of the blockMesh


Box with open top problem: +
Gravity snappyHexMesh
• In this case we are going to use the volume of
fluid (VOF) method.
• This method solves the incompressible Navier-
Stokes equations plus an additional equation to
track the phases (free surface location).
setFields
• As this is a multiphase case, we need to define
the physical properties for each phase involved
(viscosity, density and surface tension).
• The working fluids are water and air.
• Additionally, we need to define the gravity vector interFoam functionObjects
Water column and initialize the two flows.
• This is a three-dimensional and unsteady case.

Obstacle • The details of the case setup can be found in


the following reference:
A Volume-of-Fluid Based Simulation Method for Wave sampling paraview
Impact Problems.
Journal of Computational Physics 206(1):363-393.
June, 2005.
143 144

3D Dam break – Free surface flow 3D Dam break – Free surface flow

At the end of the day, you should get something like this VOF Fraction (Free surface tracking) – Very fine mesh
http://www.wolfdynamics.com/validations/3d_db/dbreak.gif

Initial conditions – Coarse mesh Solution at Time = 1 second – Coarse mesh

145 146
3D Dam break – Free surface flow 3D Dam break – Free surface flow

What are we going to do?


• Let us run this case. Go to the directory: • We will use this case to introduce the multiphase solver interFoam.
• interFoam is a solver for 2 incompressible, isothermal immiscible fluids using a VOF
(volume of fluid) phase-fraction based interface capturing approach
$PTOFC/101OF/3d_damBreak • We will define the physical properties of two phases and we are going to initialize
these phases.
• We will define the gravity vector in the dictionary g.
• After finding the solution, we will visualize the results. This is an unsteady case so
now we are going to see things moving.
• 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. • We are going to briefly address how to post-process multiphase flows.
• 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
• We are going to generate the mesh using snappyHexMesh, but for the purpose of this
automatically by typing in the terminal, for example, sh run_solver. tutorial we are not going to discuss the dictionaries.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this • Remember, different solvers have different input dictionaries.
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.

147 148

3D Dam break – Free surface flow 3D Dam break – Free surface flow
The constant directory The g dictionary file

• In this directory, we will find the following compulsory dictionary files: • This dictionary file is located in the directory
8
9
FoamFile
{
constant.
10 version 2.0;
11 format ascii;
• For multiphase flows, this dictionary is
• g 12
13
class
location
uniformDimensionedVectorField;
"constant";
compulsory.
14 object g;

• transportProperties 15
17
}

• In this dictionary we define the gravity vector (line


18 dimensions [0 1 -2 0 0 0 0];

• turbulenceProperties 19 value (0 0 -9.81);


19).
• Pay attention to the class type (line 12).

• g contains the definition of the gravity vector.


• transportProperties contains the definition of the physical properties of
each phase.
• turbulenceProperties contains the definition of the turbulence model to
use.

149 150
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The transportProperties dictionary file The turbulenceProperties dictionary file
Primary phase
• In this dictionary file we select what model we would like to use (laminar or
• This dictionary file is located in the directory turbulent).
17
18
phases (water air);
constant.
19
20
water
{
• We first define the name of the phases (line 17). • This dictionary is compulsory.
21 transportModel Newtonian;
22 nu [0 2 -1 0 0 0 0] 1e-06;
In this case we are defining the names water and
23
24 }
rho [1 -3 0 0 0 0 0] 1000;
air. The first entry in this list is the primary phase
• In this case we use a RANS turbulence model (kEpsilon).
25
26
27
air
{
(water).
28 transportModel Newtonian;
29
30
nu
rho
[0 2 -1 0 0 0 0] 1.48e-05;
[1 -3 0 0 0 0 0] 1;
• The name of the primary phase is the one you will
31 } use to initialize the solution. 17 simulationType RAS;
32
33 sigma [1 0 -2 0 0 0 0] 0.07; 18
• The name of the phases is given by the user. 19 RAS
20 {
• In this file we set the kinematic viscosity (nu),
21 RASModel kEpsilon;
density (rho) and transport model 22
(transportModel) of the phases. 23 turbulence on;
24
• We also define the surface tension (sigma).
25 printCoeffs on;
26 }

151 152

3D Dam break – Free surface flow 3D Dam break – Free surface flow
The 0 directory The file 0/alpha.water

• In this directory, we will find the dictionary files that contain the boundary and 17
18
dimensions [0 0 0 0 0 0 0];
• This file contains the boundary and initial conditions
initial conditions for all the primitive variables. 19
20
internalField uniform 0; for the non-dimensional scalar field alpha.water
21 boundaryField
• This file is named alpha.water, because the
• As we are solving the incompressible RANS Navier-Stokes equations using 22
23
{
front primary phase is water (we defined the primary
24 {
the VOF method, we will find the following field files: 25
26 }
type zeroGradient; phase in the transportProperties dictionary).
27
28
back
{
• Initially, this field is initialize as 0 in the whole domain
29 type zeroGradient; (line 19). This means that there is no water in the
30 }
• alpha.water (volume fraction of water phase) 31
32
left
{
domain at time 0. Later, we will initialize the water
33 type zeroGradient;
column and this file will be overwritten with a non-
• p_rgh (pressure field minus hydrostatic component) 34
35
}
right
uniform field for the internalField.
36 {
• For the front, back, left, right, bottom and
• U (velocity field) 37
38 }
type zeroGradient;
stlSurface patches we are using a zeroGradient
39 bottom
boundary condition (we are just extrapolating the
• k (turbulent kinetic energy field) 40
41
{
type zeroGradient; internal values to the boundary face).
42 }

• epsilon (rate of dissipation of turbulence energy field) 43


44
top
{ • For the top patch we are using an inletOutlet
45 type inletOutlet; boundary condition. This boundary condition avoids
• nut (turbulence viscosity field) 46
47
inletValue
value
uniform 0;
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 wall;
52 } (line 46).
53
54 }

153 154
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/p_rgh The file 0/U

17 dimensions [1 -1 -2 0 0 0 0]; 17 dimensions [0 -1 -1 0 0 0 0];


18 • This file contains the boundary and initial conditions 18 • This file contains the boundary and initial conditions
19 internalField uniform 0; 19 internalField uniform (0 0 0);
20 for the dimensional scalar field p_rgh. The 20 for the dimensional vector field U.
21 boundaryField dimensions of this field are given in Pascal (line 17) 21 boundaryField
22 { 22 { • We are using uniform initial conditions and the
23 front 23 front
24 { • This scalar field contains the value of the static 24 { numerical value is (0 0 0) (keyword internalField in
25 type fixedFluxPressure; 25 type fixedValue;
26 value uniform 0;
pressure field minus the hydrostatic component. 26 value uniform (0 0 0);
line 19).
27 } 27 }
28 back • This field is initialize as 0 in the whole domain (line 28 back • The front, back, left, right, bottom and stlSurface
33 left
19). 33 left
patches are no-slip walls, therefore we impose a
fixedValue boundary condition with a value of (0 0 0)
38 right • For the front, back, left, right, bottom and 38 right
at the wall.
43 bottom
stlSurface patches we are using a 43 bottom
fixedFluxPressure boundary condition (refer to the • For the top patch we are using the
48 top 48 top
49 { source code or doxygen documentation to know 49 { pressureInlterOutletVelocity boundary condition
50 type totalPressure; 50 type pressureInletOutletVelocity;
51 p0 uniform 0;
more about this boundary condition). 51 value uniform (0 0 0);
(refer to the source code or doxygen documentation
52 U U; 52 } to know more about this boundary condition).
53 phi phi; • For the top patch we are using the totalPressure 53 stlSurface
54 rho rho; 54 {
55 psi none;
boundary condition (refer to the source code or 55 type fixedValue;
56 gamma 1; doxygen documentation to know more about this 56 value uniform (0 0 0);
57 value uniform 0; 57 }
58 } boundary condition). 58
59 stlSurface 59 }
60 {
61 type fixedFluxPressure;
62 value uniform 0;
63 }
64
65 }

155 156

3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/k The file 0/epsilon

17 dimensions [0 2 -2 0 0 0 0]; 17 dimensions [0 2 -3 0 0 0 0];


18 • This file contains the boundary and initial conditions 18 • This file contains the boundary and initial conditions
19 internalField uniform 0.1; 19 internalField uniform 0.1;
20 for the dimensional scalar field k. 20 for the dimensional scalar field epsilon.
21 boundaryField 21 boundaryField
22 { • This scalar (turbulent kinetic energy), is related to the 22 { • This scalar (rate of dissipation of turbulence energy),
23 “(front|back|left|right|bottom|stlSurface)” 23 “(front|back|left|right|bottom|stlSurface)”
24 { turbulence model. 24 { is related to the turbulence model.
25 type kqRWallFunction; 25 type epsilonWallFunction;
26 value $internalField; • This field is initialize as 0.1 in the whole domain, and 26 value $internalField; • This field is initialize as 0.1 in the whole domain, and
27 } 27 }
28 all the boundary patches take the same value 28 all the boundary patches take the same value
29 top 29 top
30 {
($internalField). 30 {
($internalField).
31 type inletOutlet; 31 type inletOutlet;
32 inletValue $internalField; • For the front, back, left, right, bottom and 32 inletValue $internalField; • For the front, back, left, right, bottom and
33 value $internalField; 33 value $internalField;
34 }
stlSurface patches we are using a 34 }
stlSurface patches we are using a
35 kqRWallFunction boundary condition, which applies 35 epsilonWallFunction boundary condition, which
36 } 36 }
a wall function at the walls (refer to the source code applies a wall function at the walls (refer to the
or doxygen documentation to know more about this source code or doxygen documentation to know
boundary condition). more about this boundary condition).
• For the top patch we are using the inletOutlet • For the top patch we are using the inletOutlet
boundary condition, this boundary condition handles boundary condition, this boundary condition handles
backflow (refer to the source code or doxygen backflow (refer to the source code or doxygen
documentation to know more about this boundary documentation to know more about this boundary
condition). condition).
• We will deal with turbulence modeling later. • We will deal with turbulence modeling later.

157 158
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/nut The system directory

17
18
dimensions [0 2 -1 0 0 0 0];
• This file contains the boundary and initial conditions
• The system directory consists of the following compulsory dictionary files:
19 internalField uniform 0;
for the dimensional scalar field nut.
20
21 boundaryField • controlDict
22 { • This scalar (turbulent viscosity), is related to the
23 “(front|back|left|right|bottom|stlSurface)”
24
25
{
type nutkWallFunction;
turbulence model. • fvSchemes
26 value $internalField; • This field is initialize as 0 in the whole domain, and
27
28
}
all the boundary patches take the same value • fvSolution
29 top
30 {
($internalField).
31 type calculated;
32 value $internalField;; • For the front, back, left, right, bottom and
33 }
stlSurface patches we are using a
34
35 } nutkWallFunction boundary condition, which applies • controlDict contains general instructions on how to run the case.
a wall function at the walls (refer to the source code
or doxygen documentation to know more about this • fvSchemes contains instructions for the discretization schemes that will be
boundary condition). used for the different terms in the equations.
• For the top patch we are using the calculated
boundary condition, this boundary condition • fvSolution contains instructions on how to solve each discretized linear
computes the value of nut from k and epsilon (refer to
the source code or doxygen documentation to know
equation system.
more about this boundary condition).
• We will deal with turbulence modeling later.

159 160

3D Dam break – Free surface flow 3D Dam break – Free surface flow
The controlDict dictionary The controlDict dictionary
• This case starts from time 0 (startTime), and it will run up to 8
17 application interFoam; seconds (endTime). 55 functions • Let us take a look at the functionObjects definitions.
18 56 {
19 startFrom startTime;
• The initial time step of the simulation is 0.0001 seconds • In lines 60-76 we define the fieldMinMax functionObject
20 60 minmaxdomain
21 startTime 0; (deltaT). 61 { which computes the minimum and maximum values of
22 62 type fieldMinMax;
the field variables (p p_rgh U alpha.water k epsilon).
23
24
stopAt endTime;
• It will write the solution every 0.02 seconds (writeInterval) of 63
64 functionObjectLibs ("libfieldFunctionObjects.so");
25 endTime 8; simulation time (runTime). It will automatically adjust the time 65
26 66 enabled true; //true or false
27 deltaT 0.0001; step (adjustableRunTime), in order to save the solution at the 67
28 68 mode component;
29 writeControl adjustableRunTime;
precise write interval. 69
30 70 writeControl timeStep;
31 writeInterval 0.02; • It will keep all the solution directories (purgeWrite). 71 writeInterval 1;
32 72
33 purgeWrite 0; • It will save the solution in ascii format (writeFormat). 73 log true;
34 74
35 writeFormat ascii; 75 fields (p p_rgh U alpha.water k epsilon);
36 • The write precision is 8 digits (writePrecision). It will only save 76 }
37 writePrecision 8; eight digits in the output files.
38 144 };
39 writeCompression uncompressed;
40 • And as the option runTimeModifiable is on, we can modify all
41 timeFormat general; these entries while we are running the simulation.
42
43 timePrecision 8;
44 • In line 47 we turn on the option adjustTimeStep. This option
45 runTimeModifiable yes;
46
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 0.5; 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).
161 162
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The controlDict dictionary The controlDict dictionary

55 functions • Let us take a look at the functionObjects definitions. 55 functions • Let us take a look at the functionObjects definitions.
56 { 56 {
• In lines 81-102 we define the volRegion functionObject • In lines 107-131 we define the probes functionObject
81 water_in_domain 107 probes1
82 { which computes the volume integral (volIntegrate) of the 108 { which sample the selected fields (lines 124-127) at the
83 type volRegion; 109 type probes;
84 functionObjectLibs ("libfieldFunctionObjects.so");
field variable alpha.water in all the domain. 110 functionObjectLibs ("libsampling.so");
selected locations (lines 112-122).
85 enabled true; 111
86 • Basically, we are monitoring the quantity of water in the 112 pobeLocations • This sampling is done on-the-fly. All the information
87 enabled true; 113 (
88
domain. 114 (0.82450002 0 0.021)
sample by this functionObject is saved in the directory
89 //writeControl outputTime; 115 (0.82450002 0 0.061) ./postProcessing/probes1
90 writeControl timeStep; 116 (0.82450002 0 0.101)
91
92
writeInterval 1; 117
118
(0.82450002 0 0.141)
(0.8035 0 0.161)
• As we are sampling starting from time 0, the sampled
93 log true; 119 (0.7635 0 0.161) data will be located in the directory:
94 120 (0.7235 0 0.161)
95
96
regionType all; 121
122 );
(0.6835 0 0.161)
postProcessing/probes1/0
97 operation volIntegrate; 123
98 fields 124 fields • Feel free to open the files located in the directory
99 ( 125 (
100 alpha.water 126 p p_rgh
postProcessing/probes1/0 using your favorite text
101 ); 127 ); editor.
102 } 128
129 writeControl timeStep;
144 }; 130 writeInterval 1;
131 }

144 };

Sampling locations
(probeLocations)

163 164

3D Dam break – Free surface flow 3D Dam break – Free surface flow
The controlDict dictionary The fvSchemes dictionary
• In this case, for time discretization (ddtSchemes) we are
55 functions • Let us take a look at the functionObjects definitions. 17 ddtSchemes using the Euler method.
56 { 18 {
• In lines 135-141 we define the yplus functionObject 19 default Euler; • For gradient discretization (gradSchemes) we are using the
135 yplus 21 }
136 { which computes the yplus value. 22
Gauss linear as the default method and slope limiters
137 type yPlus; 23 gradSchemes (cellLimited) for the velocity gradient or grad(U).
138 functionObjectLibs ("libutilityFunctionObjects.so "); • This quantity is related to the turbulence modeling. 24 {
139 enabled true; 25 default Gauss linear; • For the discretization of the convective terms (divSchemes)
140 writeControl outputTime; 26 grad(U) cellLimited Gauss linear 1;
141 } • This functionObject will save the yplus field in the 27 } we are using linearUpwindV interpolation method for the
solution directories with the same saving frequency as the 28 term div(rhoPhi,U).
144 }; 29 divSchemes
solution (line 140). 30 { • For the term div(phi,alpha) we are using vanLeer
31 div(rhoPhi,U) Gauss linearUpwindV grad(U);
• It will also save the minimum, maximum and mean values 32 div(phi,alpha) Gauss vanLeer; interpolation. For the term div(phirb,alpha) we are using
33 div(phirb,alpha) Gauss linear;
of yplus in the directory: 35 div(phi,k) Gauss upwind; linear interpolation. These terms are related to the volume
36 div(phi,epsilon) Gauss upwind; fraction equation.
postProcessing/yplus 37 div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
38 } • For the terms div(phi,alpha) and div(phi,alpha) we are
39
40 laplacianSchemes using upwind (these terms are related to the turbulence
41 {
42 default Gauss linear corrected;
modeling).
43 }
44
• For the term div(((rho*nuEff)*dev2(T(grad(U))))) we are
45 interpolationSchemes using linear interpolation (this term is related to the
46 {
47 default linear; turbulence modeling).
48 }
49 • For the discretization of the Laplacian (laplacianSchemes
50 snGradSchemes
51 {
and snGradSchemes) we are using the Gauss linear
52 default corrected; corrected method
53 }
• In overall, this method is second order accurate but a little bit
diffusive. Remember, at the end of the day we want a
165 solution that is second order accurate. 166
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The fvSolution dictionary The fvSolution dictionary

17 solvers • To solve the volume fraction or alpha.water (lines 19-32) we 51 p_rghFinal • In lines 51-56 we setup the solver for p_rghFinal. This
18 { are using the smoothSolver method. 52 { correspond to the last iteration in the loop (we can use a tighter
19 "alpha.water.*" 53 $p_rgh;
20 { 54 relTol 0; convergence criteria to get more accuracy without increasing
21 nAlphaCorr 3; • In line 25 we turn on the semi-implicit method MULES. The 55 minIter 1;
22 nAlphaSubCycles 1; 56 } the computational cost)
23 cAlpha 1;
keyword nLimiterIter controls the number of MULES iterations 57
24 over the limiter. 58 "(U|UFinal)" • In lines 58-72 we setup the solvers for U and UFInal.
25 MULESCorr yes; 59 {
26
27
nLimiterIter 10;
• To have more stability it is possible to increase the number of 60
61
solver
Preconditioner
PBiCGStab;
DILU;
• In lines 74-80 we setup the solvers for the turbulent quantities,
28 solver smoothSolver; loops and corrections used to solve alpha.water (lines 21-22). 62 tolerance 1e-08; namely, k and epsilon.
29 smoother symGaussSeidel; 63 relTol 0;
30
31
tolerance
relTol
1e-8;
0;
• The keyword cAlpha (line 23) controls the sharpness of the 72
73
}

32 } interface (1 is usually fine for most cases). 74 "(k|epsilon).*"


33 75 {
34 “(pcorr|pcorrFinal)”
35 {
• In lines 34-40 we setup the solver for pcorr and pcorrFinal 76
77
solver
Preconditioner
PBiCGStab;
DILU;
36 solver PCG; (pressure correction). 78 tolerance 1e-08;
37 preconditioner DIC; 79 relTol 0;
38 tolerance 1e-8; 80 }
39 relTol 0; • In this case pcorr is solved only one time at the beginning of 81 }
40 } the computation. 82
41
42 p_rgh
43 { • In lines 42-49 we setup the solver for p_rgh.
44 solver PCG;
45 preconditioner DIC; • The keyword minIter (line 48), means that the linear solver will
46 tolerance 1e-06;
47 relTol 0.01; do at least one iteration.
48 minIter 1;
49 }

167 168

3D Dam break – Free surface flow 3D Dam break – Free surface flow
The fvSolution dictionary The system directory

82
83 PIMPLE
• In lines 83-89 we setup the entries related to the pressure- • In the system directory you will find the following optional dictionary files:
84 {
velocity coupling method used (PIMPLE in this case). Setting
85
86
momentumPredictor
nOuterCorrectors
yes;
1;
the keyword nOuterCorrectors to 1 is equivalent to running • decomposeParDict
87 nCorrectors 3; using the PISO method.
• setFieldsDict
88 nNonOrthogonalCorrectors 1;
89 } • To gain more stability we can increase the number of correctors
90
91 relaxationFactors (lines 87-88), however this will increase the computational cost.
92 {
93 fields • In lines 91-101 we setup the under relaxation factors related to
94 {
the PIMPLE method. By setting the coefficients to one we are
• decomposeParDict is read by the utility decomposePar. This dictionary
95 ".*" 1;
96 }
97 equations
not under-relaxing.
98
99
{
".*" 1; • The option momentumPredictor (line 85), is recommended for file contains information related to the mesh partitioning. This is used when
100 }
101 }
highly convective flows. running in parallel.
102

• setFieldsDict is read by the utility setFields. This utility set values on


selected cells/faces.

169 170
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The setFieldsDict dictionary The decomposeParDict dictionary
• This dictionary file is located in the directory system. • This dictionary file is located in the directory system.
• In lines 17-20 we set the default value to be 0 in the whole • This dictionary is used to decompose the domain in order to run in parallel.
17 defaultFieldValues domain (no water).
18 ( • The keyword numberOfSubdomains (line 17) is used to set the number of cores we want to use in the
19
20 );
volScalarFieldValue alpha.water 0
• In lines 22-32, we initialize a rectangular region (box) parallel simulation.
21 containing water (alpha.water 1).
22 regions • In this dictionary we also set the decomposition method (line 19).
23 ( • In this case, setFields will look for the dictionary file
24 boxToCell • Most of the times the scotch method is fine.
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. • In this case we set the numberOfSubdomains to 4, therefore we will run in parallel using 4 cores.
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) 17 numberOfSubdomains 4;
18
Air 19 method scotch;
alpha.water = 0
20
Water
alpha.water = 1

• 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:
boxToCell region processor0, processor1, processor2, and processor3.
171 172

3D Dam break – Free surface flow 3D Dam break – Free surface flow

Running the case Running the case

• Let us first generate the mesh. • Let us run the simulation in parallel using the solver interFoam.
• To generate the mesh will use snappyHexMesh (sHM), do not worry we will talk about • We will talk more about running in parallel tomorrow
sHM tomorrow. • To run the case, type in the terminal:

1. $> foamCleanTutorials 1. $> rm –rf 0


2. $> rm –rf 0 2. $> cp –r 0_org 0
3. $> blockMesh 3. $> setFields
4. $> surfaceFeatureExtract 4. $> paraFoam
5. $> snappyHexMesh -overwrite 5. $> decomposePar
6. $> createPatch -dict system/createPatchDict.0 -overwrite 6. $> mpirun –np 4 interFoam –parallel | tee log.interFoam
7. $> createPatch -dict system/createPatchDict.1 -overwrite 7. $> reconstructPar
8. $> checkMesh 8. $> paraFoam
9. $> paraFoam

173 174
3D Dam break – Free surface flow 3D Dam break – Free surface flow

Running the case • To plot the sampled data using gnuplot you can proceed as follows. To enter to the
gnuplot prompt type in the terminal:
• In steps 1-2 we copy the information of the backup directory 0_org into the directory
0. We do this because in the next step the utility setFields will overwrite the file
1. $> gnuplot
0/alpha.water, so it is a good idea to keep a backup.
• In step 3 we initialize the solution using the utility setFields. This utility reads the
dictionary setFieldsDict located in the system directory. • Now that we are inside the gnuplot prompt, we can type,
• In step 4 we visualize the initialization using paraFoam. 1. set xlabel 'Time (seconds)'
• In step 5 we use the utility decomposePar to do the domain decomposition needed
to run in parallel. 2. set ylabel 'Water volume integral'

• In step 6 we run the simulation in parallel. Notice that np means number of 3. gnuplot> plot 'postProcessing/water_in_domain/0/volRegion.dat' u 1:2 w l title
processors and the value used should be the same number as the one you set in the 'Water in domain'
dictionary decomposeParDict. 4. set xlabel 'Time (seconds)'
• If you want to run in serial, type in the terminal: interFoam | tee log
5. set ylabel 'Pressure'
• In step 7 we reconstruct the parallel solution. This step is only needed if you are
running in parallel.
6. plot 'SPHERIC_Test2/case.txt' u 1:2 w l title 'Experiment',
• Finally, in step 8 we visualize the solution. 'postProcessing/probes1/0/p' u 1:2 w l title 'Numerical simulation'
7. gnuplot> exit
To exit gnuplot
175 176

3D Dam break – Free surface flow 3D Dam break – Free surface flow
• The output of steps 3 and 6 is the following: The output screen
Courant Number mean: 0.0099001831 max: 0.50908228 Flow courant number
Interface Courant Number mean: 0.0012838336 max: 0.05362054
deltaT = 0.00061195165
Time = 0.41265658 Interface courant number. When solving multiphase flows, is always
desirable to keep the interface courant number less than 1.
PIMPLE: iteration 1
alpha.water
smoothSolver: Solving for alpha.water, Initial residual = 0.00035163885, Final residual = 9.3476388e-11, No Iterations 2
Phase-1 volume fraction = 0.20706923 Min(alpha.water) = -9.1300674e-12 Max(alpha.water) = 1.0000113 residuals
MULES: Correcting alpha.water nAlphaSubCycles 1
MULES: Correcting alpha.water nAlphaCorr 3
MULES: Correcting alpha.water
Only one loop
Phase-1 volume fraction = 0.20706923 Min(alpha.water) = -1.2354076e-07 Max(alpha.water) = 1.0000113
DILUPBiCGStab: Solving for Ux, Initial residual = 0.00057936556, Final residual = 2.3207684e-09, No Iterations 1
DILUPBiCGStab: Solving for Uy, Initial residual = 0.0021990412, Final residual = 7.228845e-09, No Iterations 1
DILUPBiCGStab: Solving for Uz, Initial residual = 0.00041048425, Final residual = 3.946807e-10, No Iterations 1
DICPCG: Solving for p_rgh, Initial residual = 0.0013260985, Final residual = 1.2556023e-05, No Iterations 4
DICPCG: Solving for p_rgh, Initial residual = 1.4873252e-05, Final residual = 8.7706547e-07, No Iterations 13
time step continuity errors : sum local = 2.166836e-08, global = -4.8300033e-11, cumulative = -5.8278026e-05 3 pressure correctors
DICPCG: Solving for p_rgh, Initial residual = 1.6925332e-05, Final residual = 8.9811533e-07, No Iterations 9 and no non-orthogonal
DICPCG: Solving for p_rgh, Initial residual = 1.1731393e-06, Final residual = 4.991128e-07, No Iterations 1 corrections
time step continuity errors : sum local = 1.2328745e-08, global = -3.6165262e-09, cumulative = -5.8281643e-05
DICPCG: Solving for p_rgh, Initial residual = 8.2834963e-07, Final residual = 4.6047958e-07, No Iterations 1
DICPCG: Solving for p_rgh, Initial residual = 4.6053278e-07, Final residual = 4.65519e-07, No Iterations 1 Tighter tolerance
time step continuity errors : sum local = 1.1498949e-08, global = -3.1908629e-09, cumulative = -5.8284834e-05
DILUPBiCGStab: Solving for epsilon, Initial residual = 0.001169828, Final residual = 9.2601488e-11, No Iterations 2 (p_rghFinal) is only applied
DILUPBiCGStab: Solving for k, Initial residual = 0.0014561556, Final residual = 9.4651262e-11, No Iterations 2 to this iteration (the final
ExecutionTime = 23.21 s ClockTime = 24 s one)
Turbulence variables residuals
fieldMinMax minmaxdomain write:

Minimum and maximum


values of field variables
min(p) = -9.8942827 in cell 5509 at location (2.490155 0.025000016 1) on processor 2
max(p) = 4703.3656 in cell 1485 at location (3.1948336 -0.425 0) on processor 2
min(p_rgh) = -7.9025882 in cell 1241 at location (0.82088765 -0.20846334 0.043756428) on processor 1
max(p_rgh) = 4831.247 in cell 3285 at location (3.1948341 -0.475 0.42499986) on processor 2
alpha.water vs. time p vs. time (at probe 0) min(U) = (-0.96505264 -0.019641482 -0.052664083) in cell 2 at location (2.1879167 -0.42500042 0.024999822) on processor 2
max(U) = (0.32541708 0.29383224 2.7117589) in cell 5246 at location (0.8884354 0.087713417 0.16296979) on processor 1
min(alpha.water) = -1.2354076e-07 in cell 2653 at location (0.84202094 -0.10628417 0.0062556498) on processor 1
max(alpha.water) = 1.0000113 in cell 224 at location (2.6411358 -0.42500003 0.074999874) on processor 2
min(k) = 0.0041733636 in cell 2510 at location (0.65789113 -0.0062500875 0.0062360099) on processor 1
max(k) = 0.83402261 in cell 6589 at location (1.2803306 -0.025028634 0.17499623) on processor 1
min(epsilon) = 0.018352121 in cell 2510 at location (0.65789113 -0.0062500875 0.0062360099) on processor 1
max(epsilon) = 11.712212 in cell 1933 at location (0.83147515 -0.19630576 0.068753535) on processor 1

volFieldValue water_in_domain write:


volIntegrate() of alpha.water = 0.66459985 Volume integral functionObject
177 178
3D Dam break – Free surface flow 3D Dam break – Free surface flow

Post-processing multiphase flows in paraFoam Post-processing multiphase flows in paraFoam


• To visualize the volume fraction, proceed as follows, • To visualize a surface representing the interface, proceed as follows,
4. To animate the solution, press Play in the 5. To animate the solution, press Play in the
VCR Controls VCR Controls

2. Select alpha.water in
the Active Variable drop-
down menu 1. Select the filter Contour

4. Press apply

3. Select Surface in the


Representation drop-down
menu

2. Select alpha.water or the field you


want to use to plot the iso-surface (it
Air Water has to be a scalar)
alpha.water = 0 alpha.water = 1

1. In the Properties tab select 3. Enter the value 0.5 which


alpha.water in Volume Fields corresponds to the interface Iso-surface representing the interface
between water and air between water and air

Interface
alpha.water = 0.5
179 180

3D Dam break – Free surface flow 3D Dam break – Free surface flow

Post-processing multiphase flows in paraFoam Exercises


• To visualize all the cells representing the water fraction, proceed as follows, • Instead of using the boundary condition totalPressure and pressureInletOutletVelocity for the patch top, try
5. To animate the solution, press Play in the to use zeroGradient. Do you get the same results? Any comments?
VCR Controls (Hint: this combination of boundary conditions will give you an error, read carefully the screen, you
will need to add a fix in 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?
1. Select the filter Threshold
• 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 at the obstacle.
4. Press apply
• 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 for the term div(phi,alpha) (fvSchemes).
Do you get the same quantitative results?
2. Select alpha.water or the field
you want to use to visualize the • Run a numerical experiment for cAlpha equal to 0, 1, and 2. Do you see any difference in the solution? What
cells (it has to be a scalar) 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?
Cells representing the • Increase the number of nOuterCorrector to 2 and study the output screen. What difference do you see?
3. Select the range you want to water location
visualize. To visualize the • Turn off the MULES corrector (MULESCorr). Do you see any difference on the solution or computing time?
water select Minimum 0.5 and
Maximum 1. • 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.

181 182
Roadmap Flow past a cylinder – From laminar to turbulent flow

1. OpenFOAM® brief overview


2. OpenFOAM® directory organization
3. Directory structure of an application/utility • At this point we all have a rough idea of what is going
4. Applications/utilities in OpenFOAM® on with all these dictionary files.

5. Directory structure of an OpenFOAM® case • Unless it is strictly necessary, from now on we will not
go into details about the dictionaries and files we are
6. Running my first OpenFOAM® case setup blindfold
using.
7. A deeper view to my first OpenFOAM® case setup
• Remember, if you are using the lab computers, do not
8. 3D Dam break – Free surface flow forget to load the environment variables.
9. Flow past a cylinder – From laminar to turbulent flow

183 184

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Flow around a cylinder – 10 < Re < 2 000 000 Workflow of the case
Incompressible and compressible flow
blockMesh
Or
fluentMeshToFoam
Physical and numerical side of the
problem:
icoFoam
• In this case we are going to solve the flow NOTE: pisoFoam
around a cylinder. We are going to use One single mesh can be used with all
pimpleFoam
solvers and utilities
incompressible and compressible solvers, in pimpleDyMFoam
laminar and turbulent regime. simpleFoam
functionObjects
• Therefore, the governing equations of the rhoPimpleFoam
interFoam
problem are the incompressible/compressible
sonicFoam
laminar/turbulent Navier-Stokes equations. potentialFoam
• We are going to work in a 2D domain. mapFields

• Depending on the Reynolds number, the flow


can be steady or unsteady.
All the dimensions are in meters • This problem has a lot of validation data. postProcessing
utilities

sampling paraview

185 186
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow

Vortex shedding behind a cylinder Some experimental (E) and numerical (N) results of the flow past a circular
cylinder at various Reynolds numbers

Creeping flow (no s eparation)


Reference cd – Re = 20 Lrb – Re = 20 cd – Re = 40 Lrb – Re = 40
S teady flow Re < 5
[1] Tritton (E) 2.22 – 1.48 –
A pair of s table vortices
in the wake
5 < Re < 40 - 46 [2] Cuntanceau and Bouard (E) – 0.73 – 1.89
S teady flow

[3] Russel and Wang (N) 2.13 0.94 1.60 2.29


Laminar vortex s treet
(Von Karman s treet)
Uns teady flow
40 - 46 < Re < 150 Drag coefficient [4] Calhoun and Wang (N) 2.19 0.91 1.62 2.18

Laminar boundary layer up to


the s eparation point, turbulent
150 < Re < 300 [5] Ye et al. (N) 2.03 0.92 1.52 2.27
Trans ition to turbulence
wake
Uns teady flow 300 < Re < 3 x 10 5
[6] Fornbern (N) 2.00 0.92 1.50 2.24
Boundary layer trans ition to 5 6
turbulent 3 x 10 < Re < 3 x 10 [7] Guerrero (N) 2.20 0.92 1.62 2.21
Uns teady flow

Turbulent vortex s treet, but the


Lrb = length of recirculation bubble, cd = drag coefficient, Re = Reynolds number,
6
wake is narrower than in the
laminar cas e 3 x 10 > Re
Uns teady flow
[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.
Strouhal number [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.
187 188

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Some experimental (E) and numerical (N) results of the flow past a circular At the end of the day, you should get something like this
cylinder at various Reynolds numbers

Reference cd – Re = 100 cl – Re = 100 cd – Re = 200 cl – Re = 200

[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

[6] Guerrero (N) 1.38 ± 0.012 ± 0.333 1.408 ± 0.048 ± 0.725

cl = lift coefficient, cd = drag coefficient, Re = Reynolds number

[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. Instantaneous velocity magnitude field Instantaneous vorticity magnitude field
[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, www.wolfdynamics.com/wiki/cylinder_vortex_shedding/movvmag.gif www.wolfdynamics.com/wiki/cylinder_vortex_shedding/movvort.gif
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. Incompressible flow – Reynolds 200

189 190
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
At the end of the day, you should get something like this
• Let us run this case. Go to the directory:

$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.

Incompressible flow – Reynolds 200 191 192

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
What are we going to do? Running the case
• We will use this case to learn how to use different solvers and utilities. • Let us first convert the mesh from a third-party format (Fluent format).
• Remember, different solvers have different input dictionaries. • You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c2
• We will learn how to convert the mesh from a third party software. • In the terminal window type:
• We will learn how to use setFields to initialize the flow field and accelerate the
convergence. 1. $> foamCleanTutorials

• We will learn how to map a solution from a coarse mesh to a fine mesh. 2. $> fluent3DMeshToFoam ../../../meshes_and_geometries/vortex_shedding/ascii.msh

• We will learn how to setup a compressible solver. 3. $> checkMesh

• We will learn how to setup a turbulence case. 4. $> paraFoam

• We will use gnuplot to plot and compute the mean values of the lift and drag
coefficients. • 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.
• We will visualize unsteady data.
• 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?

193 194
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case • 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
• To avoid this problem, type in the terminal, boundary and modify it according to your needs.

1. $> paraFoam -builtin • Let us modify the boundary dictionary file.


• In this case, we would like to setup the following numerical type boundary
• Basically, the problem is related to the names and type of the patches in the file conditions.
boundary and the boundary conditions (U, p). Notice that OpenFOAM® is telling you
what and where is the error.

Created temporary 'c2.OpenFOAM'

--> FOAM FATAL IO ERROR:

patch type 'patch' not constraint type 'empty' What Where


for patch front of field p in file "/home/joegi/my_cases_course/6/101OF/vortex_shedding/c2/0/p"

file: /home/joegi/my_cases_course/6/101OF/vortex_shedding/c2/0/p.boundaryField.front from line 60 to line 60.

From function Foam::emptyFvPatchField<Type>::emptyFvPatchField(const Foam::fvPatch&, const


Foam::DimensionedField<Type, Foam::volMesh>&, const Foam::dictionary&) [with Type = double]
in file fields/fvPatchFields/constraint/empty/emptyFvPatchField.C at line 80.

FOAM exiting

195 196

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The boundary dictionary file The boundary dictionary file

• This dictionary is located in the • The type of the cylinder patch is OK.
18 7
constant/polyMesh directory. 46 cylinder
19
20
(
out
47
48
{
type wall;
• The type of the back patch is NOT OK.
21 { • This file is automatically created when converting 49 inGroups 1(wall); Remember, this is a 2D simulation, therefore the
22 type patch; 50 nFaces 80;
23 nFaces 80; or generating the mesh. 51 startFace 18540; type should be empty.
24 startFace 18180; 52 }
25
26
}
sym1 • To get a visual reference of the patches, you can 53
54
back
{ • The type of the front patch is NOT OK.
27 { 55 type patch;
28 type symmetry;
visualize the mesh with paraFoam/paraview. 56 nFaces 9200;
Remember, this is a 2D simulation, therefore the
29 inGroups 1(symmetry); 57 startFace 18620;
type should be empty.
30 nFaces 100; • The type of the out patch is OK. 58 }
31 startFace 18260; 59 front
32 }
• The type of the sym1 patch is OK.
60 { • Remember, we assign the numerical type
33 sym2 61 type patch;
34 { 62 nFaces 9200; boundary conditions (numerical values), in the
35
36
type
inGroups
symmetry;
1(symmetry);
• The type of the sym2 patch is OK. 63
64 }
startFace 27820;
field files found in the directory 0
37 nFaces 100; 65 )
38 startFace 18360; • The type of the in patch is OK.
39 }
40 in
41 {
42 type patch;
43 nFaces 80;
44 startFace 18460;
45 }

197 198
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• At this point, check that the name and type of the base type boundary conditions Running the case
and numerical type boundary conditions are consistent. If everything is ok, we are
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c2
ready to go.
• Do not forget to explore the rest of the dictionary files, namely: • In the folder c1 you will find the same setup, but to generate the mesh we use
blockMesh (the mesh is identical).
• 0/p (p is defined as relative pressure)
• To run this case, in the terminal window type:
• 0/U
• constant/transportProperties
1. $> renumberMesh -overwrite
• system/controlDict
2. $> icoFoam | tee log.icofoam
• system/fvSchemes
$> pyFoamPlotWatcher.py log.icofoam
• system/fvSolution 3.
You will need to launch this script in a different terminal
• Reminder: $> gnuplot scripts0/plot_coeffs
4.
• The diameter of the cylinder is 2.0 m. You will need to launch this script in a different terminal

• And we are targeting for a Re = 200. 5. $> paraFoam

199 200

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case • At this point try to use the following utilities. In the terminal type:
• In step 1 we use the utility renumberMesh to make the linear system more diagonal • $> 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
dominant, this will speed-up the linear solvers. This is inexpensive (even for large solution in the directory 0. If you do not add the –noZero option, it will compute and write the vorticity field for all the
meshes), therefore is highly recommended to always do it. saved solutions, including 0
• $> postprocess –func 'grad(U)' –latestTime
• In step 2 we run the simulation and save the log file. Notice that we are sending the This utility will compute and write the velocity gradient or grad(U) in the whole domain (including at the walls). The
job to background. –latestTime option means compute the velocity gradient only for the last saved solution.

• In step 3 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the • $> postprocess –func 'grad(p)'
This utility will compute and write the pressure gradient or grad(U) in the whole domain (including at the walls).
job is running in background, we can launch this utility in the same terminal tab.
• $> foamToVTK –time 50:300
• In step 4 we use the gnuplot script scripts0/plot_coeffs to plot the force 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
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.
• $> postProcess -func 'div(U)'
and error message, try to fix it.
These last three will give you

• The force coefficients are computed using functionObjects. This utility will compute and write the divergence of the velocity field or grad(U) in the whole domain (including at the
walls).
• After the simulation is over, we use paraFoam to visualize the results. Remember to • $> pisoFoam -postProcess -func CourantNo
use the VCR Controls to animate the solution. 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
• In the folder c1 you will find the same setup, but to generate the mesh we use 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.
blockMesh (the mesh is identical).
• $> 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.
201 202
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Non-uniform field initialization • Let us run the same case but using a non-uniform field
• In the previous case, it took about 150 seconds of simulation time to onset the instability. The setFieldsDict dictionary
• If you are not interested in the initial transient or if you want to speed-up the computation, you • This dictionary file is located in the directory system.
can add a perturbation in order to trigger the onset of the instability.
17 defaultFieldValues • In lines 17-20 we set the default value of the velocity vector
• Let us use the utility setFields to initialize a non-uniform flow. 18
19
(
volVectorFieldValue U (1 0 0) to be (0 0 0) in the whole domain.
20 );
• This case is already setup in the directory , 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
$PTOFC/101OF/vortex_shedding/c3 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 ( and it will overwrite the original values according to the
• As you saw in the previous example, icoFoam is a very basic solver that does not have access 29
30 );
volVectorFieldValue U (0.98480 0.17364 0)
regions defined in setFieldsDict.
to all the advanced modeling or postprocessing capabilities that comes with OpenFOAM®. 31
32 );
}

• Therefore, instead of using icoFoam we will use pisoFoam (or pimpleFoam) from now on. boxToCell region
• To run the solver pisoFoam (or pimpleFoam) starting from the directory structure of an

U (0.98480 0.17364 0)
icoFoam case, you will need to add the followings modifications:

U (1 0 0)
• Add the file turbulenceProperties 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).
203 204

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• Let us run the same case but using a non-uniform field. Running the case – Non-uniform field initialization
• 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 • In step 2 we generate the mesh using blockMesh. The name and type of the
use blockMesh. patches are already set in the dictionary blockMeshDict so there is no need to
• To run this case, in the terminal window type: modify the boundary file.

1. $> foamCleanTutorials • In step 4 we copy the original files to the directory 0. We do this to keep a backup of
the original files as the file 0/U will be overwritten when using setFields.
2. $> blockMesh
• In step 5 we initialize the solution using setFields.
3. $> rm –rf 0 > /dev/null 2>&1
• In step 6 we use the utility renumberMesh to make the linear system more diagonal
4. $> cp –r 0_org/ 0 dominant, this will speed-up the linear solvers.
5. $> setFields • In step 7 we run the simulation and save the log file. Notice that we are sending the
$> renumberMesh -overwrite job to background.
6.
• In step 8 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
7. $> pisoFoam | tee log.pisofoam
job is running in background, we can launch this utility in the same terminal tab.
$> pyFoamPlotWatcher.py log.pisofoam
8. • In step 9 we use the gnuplot script scripts0/plot_coeffs to plot the lift and drag
You will need to launch this script in a different terminal
coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
$> gnuplot scripts0/plot_coeffs monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
9.
You will need to launch this script in a different terminal

10. $> paraFoam 205 206


Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Does non-uniform field initialization make a difference? For how long should run the simulation?
• A picture is worth a thousand words. No need to tell you yes, even if the solutions are
slightly different. • This is the difficult part when dealing with
• This bring us to the next subject, for how long should we run the simulation? unsteady flows.
• Usually you run the simulation until the
behavior of a quantity of interest does not
oscillates or it becomes periodic.
• In this case we can say that after the 50
seconds mark the solution becomes
periodic, therefore there is no need to run up
to 350 seconds (unless you want to gather a
lot of statistics).
• We can stop the simulation at 150 seconds
(or maybe less), and do the average of the
quantities between 100 and 150 seconds.

No field initialization With field initialization

207 208

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
What about the residuals? How to compute force coefficients

68 functions • To compute the force coefficients we use


• Residuals are telling you a lot, but they are 69 { functionObjects.
difficult to interpret. 195
196
forceCoeffs_object
{
• Remember, functionObjects are defined at the end of
205 type forceCoeffs; the controlDict dictionary file.
• In this case the fact that the initial residuals 206 functionObjectLibs ("libforces.so");

are increasing after about 10 seconds, does 208 patches (cylinder); • In line 195 we give a name to the functionObject.
209

not mean that the solution is diverging. This 210 pName p; • In line 208 we define the patch where we want to
211 Uname U;
212 rhoName rhoInf; compute the forces.
is in indication that something is happening 213 rhoInf 1.0;
(in this case the onset of the instability). 214 • In lines 212-213 we define the reference density value.
215 //// Dump to file
216 log true; • In line 218 we define the center of rotation (for moments).
• Remember, the residuals should always 217
218 CofR (0.0 0 0); • In line 219 we define the lift force axis.
drop to the tolerance criteria set in the 219 liftDir (0 1 0);
• In line 220 we define the drag force axis.
fvSolution dictionary (final residuals). If 220
221
dragDir (1 0 0);
pitchAxis (0 0 1);
222 magUInf 1.0; • In line 221 we define the axis of rotation for moment
they do not drop to the desired tolerance, we 223 lRef 1.0;
224 Aref 2.0;
computation.
are talking about unconverged time-steps. 225
226 outputControl timeStep;
• In line 223 we give the reference length (for computing
• Things that are not clear from the residuals: 227 outputInterval 1; the moments)
228 }

• For how long should we run the • In line 224 we give the reference area (in this case the
255 };
frontal area).
simulation?
• The output of this functionObject is saved in the file
• Is the solution converging to the right forceCoeffs.dat located in the directory
value? forceCoeffs_object/0/

209 210
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Can we compute basic statistics of the force coefficients using gnuplot? On the solution accuracy
• Yes we can. Enter the gnuplot prompt and type: • At the end of the day we want a solution that is second order
17 ddtSchemes
18 { accurate.
20 default backward;
22
23
}
• We define the discretization schemes (and therefore the
1. gnuplot> stats ‘postProcessing/forceCoeffs_object/0/forceCoeffs.dat’ u 3
24 gradSchemes accuracy) in the dictionary fvSchemes.
This will compute the basic statistics of all the rows in the file forceCoeffs.dat (we are sampling column 3 in the input file) 25 {
29
35 }
default cellLimited leastSquares 1;
• In this case, for time discretization (ddtSchemes) we are
2. gnuplot> stats ‘postProcessing/forceCoeffs_object/0/forceCoeffs.dat’ every ::3000::7000 u 3 36 using the backward method.
This will compute the basic statistics of rows 3000 to 7000 in the file forceCoeffs.dat (we are sampling column 3 in the input file) 37 divSchemes
38
39
{
default none;
• For gradient discretization (gradSchemes) we are using the
3. gnuplot> plot ‘postProcessing/forceCoeffs_object/0/forceCoeffs.dat’ u 3 w l 43 div(phi,U) Gauss linearUpwindV default; leastSquares method with slope limiters (cellLimited) for all
This will plot column 3 against the row number (iteration number) 48 div((nuEff*dev2(T(grad(U))))) Gauss linear;
49 } terms (default option).
50
4. gnuplot> exit 51 laplacianSchemes • Sometimes adding a gradient limiter to the pressure gradient
To exit gnuplot 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 default linear;
we are using linearUpwindV interpolation method for the
• Remember the force coefficients information is saved in the file forceCoeffs.dat
59 }
60 term div(rho,U).
61 snGradSchemes
located in the directory postProcessing/forceCoeffs_object/0 62 {
• For the discretization of the Laplacian (laplacianSchemes
63 default limited 1;
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).
211 212

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
On the solution tolerance and linear solvers On the runtime parameters

17 solvers
• We define the solution tolerance and linear solvers in the 17 application pisoFoam;
• This case starts from the latest saved solution (startFrom).
18 { dictionary fvSolution. 18
31 p 20 startFrom latestTime; • In this case as there are no saved solutions, it will start from
32
33
{
solver GAMG;
• To solve the pressure (p) we are using the GAMG method 21
22 startTime 0;
0 (startTime).
34 tolerance 1e-6; with an absolute tolerance of 1e-6 and a relative tolerance 23
35 relTol 0; 24 stopAt endTime; • It will run up to 350 seconds (endTime).
36 smoother GaussSeidel; relTol of 0.01. 26
37 nPreSweeps 0; 27 endTime 350; • The time step of the simulation is 0.05 seconds (deltaT). The
38 nPostSweeps 2; • The entry pFinal refers to the final correction of the PISO 28
39 cacheAgglomeration on; 29 deltaT 0.05; time step has been chosen in such a way that the Courant
40 agglomerator faceAreaPair; loop. It is possible to use a tighter convergence criteria only 30
41 nCellsInCoarsestLevel 100; 31 writeControl runTime;
number is less than 1
42 mergeLevels 1;
in the last iteration. 32
43 } 33 writeInterval 1; • It will write the solution every 1 second (writeInterval) of
44 • To solve U we are using the solver PBiCGStab and the DILU 34
45 pFinal 35 purgeWrite 0;
simulation time (runTime).
46 {
preconditioner, with an absolute tolerance of 1e-8 and a 36
47 $p; relative tolerance relTol of 0 (the solver will stop iterating 37 writeFormat ascii; • It will keep all the solution directories (purgeWrite).
48 relTol 0; 38
when it meets any of the conditions).
49
50
} 39
40
writePrecision 8; • It will save the solution in ascii format (writeFormat).
51 U • Solving for the velocity is relative inexpensive, whereas 41 writeCompression off;
52 { 42 • The write precision is 8 digits (writePrecision).
53 solver PBiCGStab; solving for the pressure is expensive. 43 timeFormat general;
54 preconditioner DILU; 44 • And as the option runTimeModifiable is on, we can modify
55 tolerance 1e-08; • The PISO sub-dictionary contains entries related to the 45 timePrecision 6;
56 relTol 0; 46 all these entries while we are running the simulation.
57 } pressure-velocity coupling (in this case the PISO method). 47 runTimeModifiable true;
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 }

213 214
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The output screen Let us use a potential solver to find a quick solution
• This is the output screen of the pisoFoam solver. • In this case we are going to use the potential solver potentialFoam (remember potential
nCorrector 1

solvers are inviscid, irrotational and incompressible)


Time = 350

Courant Number mean: 0.11299953 max: 0.87674198


Courant number
• This solver is super fast and it can be used to find a solution to be used as initial conditions
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
(non-uniform field) for an incompressible solver.
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 • A good initial condition will accelerate and improve the convergence rate.
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 • This case is already setup in the directory
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

faceSource inMassFlow output:


$PTOFC/101OF/vortex_shedding/c4
sum(in) of phi = -40 Mass flow at in patch
nCorrector 2

faceSource outMassFlow output:


sum(out) of phi = 40 Mass flow at out patch

fieldAverage fieldAverage output:


• Do not forget to explore the dictionary files.
Calculating averages Computing averages of fields
nCorrectors 2
• The following dictionaries are different
Writing average fields

forceCoeffs forceCoeffs_object output: • system/fvSchemes


Cm = 0.0043956828
Cd
Cl
=
=
1.4391786
0.44532594 Force
• system/fvSolution
Cl(f) = 0.22705865 coefficients
Cl(r) = 0.21826729

fieldMinMax minmaxdomain output:


min(p) = -0.82758125 at location (2.2845502 0.27072681 1.4608125e-17)
max(p) = 0.55952746 at location (-1.033408 -0.040619346 0)
Try to spot the differences.
min(U) = (-0.32263726 -0.054404584 -1.8727033e-19) at location (2.4478235 -0.69065656 -2.5551406e-17) Min and max values
max(U) = (1.4610304 0.10220218 2.199981e-19) at location (0.43121241 1.5285504 -1.4453535e-17)

215 216

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case – Let us use a potential solver to find a quick solution Running the case – Let us use a potential solver to find a quick solution

• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c4 • In step 2 we generate the mesh using blockMesh. The name and type of the
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this patches are already set in the dictionary blockMeshDict so there is no need to
case we will use blockMesh. modify the boundary file.
• In step 4 we copy the original files to the directory 0. We do this to keep a backup of
• To run this case, in the terminal window type:
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
1. $> foamCleanTutorials
conflicts with the functionobjects. The options –writep and –writePhi will write
2. $> blockMesh the pressure field and fluxes respectively.
3. $> rm –rf 0 • 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
4. $> cp –r 0_org 0
you are looking to run. Have in mind that the meshes need to be the same.
5. $> potentialFoam –noFunctionObjects –initialiseUBCs –writep -writePhi
• Be careful with the name and type of the boundary conditions, they should be same
6. $> paraFoam between the potential case and incompressible case.

217 218
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Potential solution The output screen
• Using a potential solution as initial conditions is much better than using a uniform • This is the output screen of the potentialFoam solver.
flow. It will speed up the solution and it will give you more stability. • The output of this solver is also a good indication of the sensitivity of the mesh quality
• Finding a solution using the potential solver is inexpensive. 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.

Calculating potential flow Velocity computation


DICPCG: Solving for Phi, Initial residual = 2.6622265e-05, Final residual = 8.4894837e-07, No Iterations 27 Initial approximation
DICPCG: Solving for Phi, Initial residual = 1.016986e-05, Final residual = 9.5168103e-07, No Iterations 9
DICPCG: Solving for Phi, Initial residual = 4.0789046e-06, Final residual = 7.7788216e-07, No Iterations 5
DICPCG: Solving for Phi, Initial residual = 1.8251249e-06, Final residual = 8.8483568e-07, No Iterations 1
DICPCG: Solving for Phi, Initial residual = 1.1220074e-06, Final residual = 5.6696809e-07, No Iterations 1
DICPCG: Solving for Phi, Initial residual = 7.1187246e-07, Final residual = 7.1187246e-07, No Iterations 0
Continuity error = 1.3827583e-06
Interpolated velocity error = 7.620206e-07
nNonOrthogonalCorrectors 5
Calculating approximate pressure field Pressure computation
DICPCG: Solving for p, Initial residual = 0.0036907012, Final residual = 9.7025397e-07, No Iterations 89
DICPCG: Solving for p, Initial residual = 0.0007470416, Final residual = 9.9942495e-07, No Iterations 85
DICPCG: Solving for p, Initial residual = 0.00022829496, Final residual = 8.6107759e-07, No Iterations 36
DICPCG: Solving for p, Initial residual = 7.9622793e-05, Final residual = 8.4360883e-07, No Iterations 31
DICPCG: Solving for p, Initial residual = 2.8883108e-05, Final residual = 8.7152873e-07, No Iterations 25
Velocity field Pressure field DICPCG: Solving for p,
ExecutionTime = 0.17 s
Initial residual
ClockTime = 0 s
= 1.151539e-05, Final residual = 9.7057871e-07, No Iterations 9

End

219 220

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Let us map a solution from a coarse mesh to a finer mesh Running the case – 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). • You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c6
• For instance, you can compute a full Navier-Stokes solution in a coarse mesh (fast • To generate the mesh, use blockMesh (remember this mesh is finer).
solution), and then map it to a finer mesh.
• To run this case, in the terminal window type:
• 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
1. $> foamCleanTutorials
utility mapFields.
• This case is already setup in the directory 2. $> blockMesh
3. $> rm –rf 0
$PTOFC/101OF/vortex_shedding/c6 4. $> cp –r 0_org 0
5. $> mapfields ../c4 –consistent –noFunctionObjects –mapMethod cellPointInterpolate -sourceTime 0

6. $> paraFoam

• To run step 5 you need to have a solution in the directory ../c4

221 222
Flow past a cylinder – From laminar to turbulent flow 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 The meshes and the mapped fields

Coarse mesh Fine 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: mapFields
• 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.

223 224

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The output screen Setting a turbulent case
• This is the output screen of the mapFields utility. • So far we have used laminar incompressible solvers.
• The utility mapFields, will try to interpolate all fields in the source directory. • Let us do a turbulent simulation.
• You can control the target time via the startFrom and startTime keywords in the • When doing turbulent simulations, we need to choose the turbulence model, define
controlDict dictionary file. the boundary and initial conditions for the turbulent quantities, and modify the
Source case
fvSchemes and fvSolution dictionaries to take account for the new variables we
Source: "/home/joegi/my_cases_course/6x/101OF/vortex_shedding" "c5"
Target: "/home/joegi/my_cases_course/6x/101OF/vortex_shedding" "c6" Target case are solving (the transported turbulent quantities).
Mapping method: cellPointInterpolate Interpolation method

Create databases as time


• This case is already setup in the directory
Source time: 350 Source time
Target time: 0 Target time
Create meshes $PTOFC/101OF/vortex_shedding/c14
Source mesh size: 9200 Target mesh size: 36800 Source and target mesh cell count

Consistently creating and mapping fields for time 0

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. 225 226
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• The following dictionaries remain unchanged The transportProperties dictionary file
• system/blockMeshDict • This dictionary file is located in the directory constant.
• constant/polyMesh/boundary • In this file we set the transport model and the kinematic viscosity (nu).
• 0/p
• 0/U
16 transportModel Newtonian;
17
19 nu nu [ 0 2 -1 0 0 0 0 ] 0.0002;
• The following dictionaries need to be adapted for the turbulence case
• constant/transportProperties
• system/controlDict • Reminder:
• system/fvSchemes • The diameter of the cylinder is 2.0 m.
• system/fvSolution • And we are targeting for a Re = 10000.

• The following dictionaries need to be adapted for the turbulence case


• constant/turbulenceProperties
227 228

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The turbulenceProperties dictionary file The controlDict dictionary
• This dictionary file is located in the directory constant.
17 application pimpleFoam;
• This case will start from the last saved solution (startFrom). If there is
• In this dictionary file we select what model we would like to use (laminar or turbulent). 18
20 startFrom latestTime;
no solution, the case will start from time 0 (startTime).
21 • It will run up to 500 seconds (endTime).
• In this case we are interested in modeling turbulence, therefore the dictionary is as follows 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
17 simulationType RAS; 27 (runTime).
RANS type simulation
28 deltaT 0.001;
18 32 • It will keep all the solution directories (purgeWrite).
33 writeControl runTime;
19 RAS RANS sub-dictionary
41 • It will save the solution in ascii format (writeFormat).
20 { 42 writeInterval 1;
43
21 RASModel kOmegaSST; RANS model to use
50 purgeWrite 0;
• The write precision is 8 digits (writePrecision).
22 51
52 writeFormat ascii; • And as the option runTimeModifiable is on, we can modify all these
23 turbulence on; Turn on/off turbulence. Runtime modifiable
53 entries while we are running the simulation.
24 54 writePrecision 8;
25 printCoeffs on; Print coefficients at the beginning 55 • In line 64 we turn on the option adjustTimeStep. This option will
56 writeCompression off;
26 } 57 automatically adjust the time step to achieve the maximum desired
58 timeFormat general; courant number maxCo (line 66).
59
60 timePrecision 6; • We also set a maximum time step maxDeltaT in line 67.
61
62 runTimeModifiable yes; • Remember, the first time step of the simulation is done using the value
63
64 adjustTimeStep yes; set in line 28 and then it is automatically scaled to achieve the desired
• If you want to know the models available use the banana method. 65
66 maxCo 0.9;
maximum values (lines 66-67).
67 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.

229 230
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The fvSchemes dictionary The fvSolution dictionary

• In this case, for time discretization (ddtSchemes) we are using the 17 solvers
• To solve the pressure (p) we are using the GAMG method, with an
17 ddtSchemes blended CrankNicolson method. The blending coefficient goes from 0 18 { absolute tolerance of 1e-6 and a relative tolerance relTol of 0.001.
18 { 31 p
21 default CrankNicolson 0.5; to 1, where 0 is equivalent to the Euler method and 1 is a pure Crank Notice that we are fixing the number of minimum iterations (minIter).
32 {
22 } Nicolson. 33 solver GAMG;
24 gradSchemes 34 tolerance 1e-6;
• To solve the final pressure correction (pFinal) we are using the PCG
25 { • For gradient discretization (gradSchemes) we are using as default 35 relTol 0.001; method with the DIC preconditioner, with an absolute tolerance of 1e-6
31 default cellLimited leastSquares 1; 36 smoother GaussSeidel;
36 grad(U) cellLimited Gauss linear 1; option the leastSquares method. For grad(U) we are using Gauss and a relative tolerance relTol of 0.
37 nPreSweeps 0;
37 } linear with slope limiters (cellLimited). You can define different 38 nPostSweeps 2;
39 divSchemes • Notice that we can use different methods between p and pFinal. In this
40 {
methods for every term in the governing equations, for example, you 39 cacheAgglomeration on;
40 agglomerator faceAreaPair; case we are using a tighter tolerance for the last iteration.
41 default none; can define a different method for grad(p). 41 nCellsInCoarsestLevel 100;
47 div(phi,U) Gauss linearUpwindV grad(U); 42 mergeLevels 1; • We are also fixing the number of minimum iterations (minIter). This
49 div((nuEff*dev2(T(grad(U))))) Gauss linear; • For the discretization of the convective terms (divSchemes) we are 44 minIter 2;
51 div(phi,k) Gauss linearUpwind default; entry is optional.
52 div(phi,omega) Gauss linearUpwind default;
using linearUpwindV interpolation method with slope limiters for the 45 }
46
63 } term div(phi,U). 47 pFinal • To solve U we are using the solver PBiCGStab with the DILU
65 laplacianSchemes 48 { preconditioner, an absolute tolerance of 1e-8 and a relative tolerance
66 { • For the terms div(phi,k) and div(phi,omega) we are using 49 solver PCG;
74 default Gauss linear limited 1; relTol of 0. Notice that we are fixing the number of minimum iterations
75 }
linearUpwind interpolation method with no slope limiters. These terms 50 preconditioner DIC;
51 tolerance 1e-06; (minIter).
77 interpolationSchemes are related to the turbulence modeling. 52 relTol 0;
78 { 54 minIter 3;
79 default linear; • For the term div((nuEff*dev2(T(grad(U))))) we are using linear 55 }
81 }
83 snGradSchemes
interpolation (this term is related to turbulence modeling). 56
57 U
84 {
86 default limited 1; • For the discretization of the Laplacian (laplacianSchemes and 58 {
59 solver PBiCGStab;
87 } snGradSchemes) we are using the Gauss linear limited 1 method. 60 preconditioner DILU;
89 wallDist 61 tolerance 1e-08;
90 { • To compute the distance to the wall and normals to the wall, we use the 62 relTol 0;
91 method meshWave; 63 minIter 3;
92 } method meshWave. This only applies when using wall functions
64 }
(turbulence modeling).
• This method is second order accurate.

231 232

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary The fvSolution dictionary

17 solvers
• To solve UFinal we are using the solver PBiCGStab with an absolute 113 kFinal
• To solve kFinal 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 114 { tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
77 UFinal fixing the number of minimum iterations (minIter). 115 solver PBiCGStab; fixing the number of minimum iterations (minIter).
78 { 116 preconditioner DILU;
79 solver PBiCGStab; 117 tolerance 1e-08;
80 preconditioner DILU;
• To solve omega and omegaFinal we are using the solver PBiCGStab 118 relTol 0;
• In lines 123-133 we setup the entries related to the pressure-velocity
81 tolerance 1e-08; with an absolute tolerance of 1e-8 and a relative tolerance relTol of 0. 119 minIter 3; coupling method used (PIMPLE in this case). Setting the keyword
82 relTol 0; Notice that we are fixing the number of minimum iterations (minIter). 120 } nOuterCorrectors to 1 is equivalent to running using the PISO method.
83 minIter 3; 121 }
84 } 122
85
• To solve k we are using the solver PBiCGStab with an absolute 123 PIMPLE
• To gain more stability we are using 1 outer correctors
86 omega tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are 124 { (nOuterCorrectors), 3 inner correctors or PISO correctors
87 { fixing the number of minimum iterations (minIter). 126 nOuterCorrectors 1; (nCorrectors), and 1 correction due to non-orthogonality
88 solver PBiCGStab; 127 //nOuterCorrectors 2;
89 preconditioner DILU; 128 (nNonOrthogonalCorrectors).
90 tolerance 1e-08; 129 nCorrectors 3;
91 relTol 0; 130 nNonOrthogonalCorrectors 1; • Remember, adding corrections increase the computational cost.
92 minIter 3; 133 }
93 } 134 • In lines 135-147 we setup the under relaxation factors used during the
94 135 relaxationFactors
95 omegaFinal 136 {
outer corrections (pseudo transient iterations). If you are working in
96 { 137 fields PISO mode (only one outer correction or nOuterCorrectors), these
97 solver PBiCGStab; 138 { values are ignored.
98 preconditioner DILU; 139 p 0.3;
99 tolerance 1e-08; 140 }
100 relTol 0; 141 equations
101 minIter 3; 142 {
102 } 143 U 0.7;
103 144 k 0.7;
104 k 145 omega 0.7;
105 { 146 }
106 solver PBiCGStab; 147 }
107 preconditioner DILU;
108 tolerance 1e-08;
109 relTol 0;
110 minIter 3;
111 }

233 234
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• The following dictionaries are new Turbulence model free-stream boundary conditions
• 0/k
• The initial value for the turbulent kinetic energy can be found as follows
• 0/omega
• 0/nut
These are the field variables related to the closure equations of the turbulent • The initial value for the specific kinetic energy can be found as follows
model.

• As we are going to use the model we need to define the initial • Where is the viscosity ratio and is the turbulence intensity.
conditions and boundaries conditions.
• If you are working with external aerodynamics or virtual wind tunnels, you can use the following
• To define the IC/BC we will use the free stream values of and 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.
• In the following site, you can find a lot information abut choosing initial and
boundary conditions for the different turbulence models: Low Medium High

• https://turbmodels.larc.nasa.gov/ 1.0 % 5.0 % 10.0 %

1 10 100
235 236

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The file 0/k The file 0/omega
19 internalField uniform 0.075;
19 internalField uniform 0.00015; 20
20 • We are using uniform initial conditions (line 19). 21 boundaryField • We are using uniform initial conditions (line 19).
21 boundaryField 22 {
22 { • For the in patch we are using a fixedValue boundary 23 out • For the in patch we are using a fixedValue boundary
23 out 24 {
24 { condition. 25 type inletOutlet; condition.
25 type inletOutlet; 26 inletValue uniform 0.075;
26 inletValue uniform 0.00015; • For the out patch we are using an inletOutlet boundary 27
28 }
value uniform 0.075; • For the out patch we are using an inletOutlet boundary
27 value uniform 0.00015;
28 } condition (this boundary condition avoids backflow). 29 sym1 condition (this boundary condition avoids backflow).
29 sym1 30 {
30
31
{
type symmetryPlane;
• For the cylinder patch (which is base type wall), we 31
32 }
type symmetryPlane;
• For the cylinder patch (which is base type wall), we
32 } are using the kqRWallFunction boundary condition. 33 sym2 are using the omegaWallFunction boundary condition.
33 sym2 34 {
34 {
This is a wall function, we are going to talk about this 35 type symmetryPlane; 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
when we deal with turbulence modeling. Remember, we
36 }
37 in we can use wall functions only if the patch is of base 38 { can use wall functions only if the patch is of base type
38 { 39 type fixedValue;
39 type fixedValue;
type wall. 40 value uniform 0.075;
wall.
40 value uniform 0.00015; 41 }
41 } • The rest of the patches are constrained. 42 cylinder • The rest of the patches are constrained.
42 cylinder 43 {
43
44
{
type kqRWallFunction;
• FYI, the inlet velocity is 1 and the turbulence intensity is 44
45
type
Cmu
omegaWallFunction;
0.09;
• FYI, the inlet velocity is 1 and the eddy viscosity ratio is
45 value uniform 0.00015; equal to 1%. 46 kappa 0.41; equal to 10.
46 } 47 E 9.8;
47
48
back
{
• We will study with more details how to setup the 48
49
beta1
value
0.075;
uniform 0.075;
• We will study with more details how to setup the
49 type empty; boundary conditions when we deal with turbulence 50 } boundary conditions when we deal with turbulence
50 } 51 back
51 front modeling in the advanced modules. 52 { modeling in the advanced modules.
52 { 53 type empty;
53 type empty; 54 }
54 } 55 front
55 } 56 {
57 type empty;
58 }
59 }
237 238
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The file 0/nut Running the case – Setting a turbulent case
19 internalField uniform 0; • You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c14
20 • We are using uniform initial conditions (line 19).
21 boundaryField
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this case we will use
22 { • For the in patch we are using the calculated boundary
23 out blockMesh.
24 { condition (nut is computed from kappa and omega)
25 type calculated;
• To run this case, in the terminal window type:
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 {
omega) $> foamCleanTutorials
30
31 }
type symmetryPlane;
1.
32 sym2 • For the cylinder patch (which is base type wall), we
33
34
{
type symmetryPlane; are using the nutkWallFunction boundary condition. 2. $> blockMesh
35 } This is a wall function, we are going to talk about this
36
37
in
{ when we deal with turbulence modeling. Remember, we 3. $> renumberMesh -overwrite
38 type calculated;
can use wall functions only if the patch is of base type
39 value uniform 0; $> pimpleFoam | tee log.solver
40
41
}
cylinder
wall. 4.
42 {
You will need to launch this script in a different terminal
43 type nutkWallFunction; • The rest of the patches are constrained.
44 Cmu 0.09; $> pyFoamPlotWatcher.py log.solver
45 kappa 0.41; • Remember, the turbulent viscosity (nut) is equal to 5.
46 E 9.8; You will need to launch this script in a different terminal
47 value uniform 0;
48
49
}
back $> gnuplot scripts0/plot_coeffs
50 { 6.
51 type empty; You will need to launch this script in a different terminal
52 } • We will study with more details how to setup the
53 front
7. $> pimpleFoam –postprocess –func yPlus –latestTime -noFunctionObjects
54 { boundary conditions when we deal with turbulence
55 type empty;
modeling in the advanced modules.
56
57 }
}
8. $> paraFoam
239 240

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
pimpleFoam output screen
Running the case – Setting a turbulent case
Courant Number mean: 0.088931706 max: 0.90251464 Courant number
deltaT = 0.040145538 Time step
Time = 499.97 Simulation time

• In step 3 we use the utility renumberMesh to make the linear system more diagonal 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
dominant, this will speed-up the linear solvers. 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
• In step 4 we run the simulation and save the log file. Notice that we are sending the 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
job to background. 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
• In step 5 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the 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
job is running in background, we can launch this utility in the same terminal tab. 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
pFinal
• In step 6 we use the gnuplot script scripts0/plot_coeffs to plot the force DICPCG: Solving for p, Initial residual = 0.00031459519, Final residual = 9.4260163e-07, No Iterations 36
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
coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to 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
monitor a quantity of interest. Feel free to take a look at the script and to reuse it. ExecutionTime = 1689.51 s ClockTime = 1704 s

fieldAverage fieldAverage output:


• In step 7 we use the utility postProcess to compute the value of each saved Calculating averages Message letting you know that
the variable is becoming
kappa and omega residuals
forceCoeffs forceCoeffs_object output:
solution (we are going to talk about when we deal with turbulence modeling). Cm = 0.0023218797
unbounded
Cd = 1.1832452
Cl = -1.3927646 Force coefficients
Cl(f) = -0.69406044
Cl(r) = -0.6987042

fieldMinMax minmaxdomain output:


min(p) = -1.5466372 at location (-0.040619337 -1.033408 0)
max(p) = 0.54524589 at location (-1.033408 0.040619337 1.4015759e-17)
min(U) = (0.94205232 -1.0407426 -5.0319219e-19) at location (-0.70200781 -0.75945224 -1.3630525e-17)
max(U) = (1.8458167 0.0047368607 4.473279e-19) at location (-0.12989625 -1.0971865 2.4694467e-17) Minimum and
min(k) = 1e-15 at location (1.0972618 1.3921931 -2.2329889e-17) maximum values
max(k) = 0.055400108 at location (2.1464795 0.42727634 0)
min(omega) = 0.2355751 at location (29.403674 19.3304 0)
241 max(omega) = 21.477072 at location (1.033408 0.040619337 1.3245285e-17) 242
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The output screen Using a compressible solver
• This is the output screen of the yPlus utility. • So far we have only used incompressible solvers.
• Let us use the compressible solver rhoPimpleFoam, which is a,
Time = 500.01
Reading field U
Transient solver for laminar or turbulent flow of compressible fluids for HVAC and
Reading/calculating face flux field phi similar applications. Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-
Transport model
Selecting incompressible transport model Newtonian resolved and pseudo-transient simulations.
Selecting RAS turbulence model kOmegaSST Turbulence model
kOmegaSSTCoeffs Model coefficients
{
alphaK1 0.85;
alphaK2 1; • When working with compressible solver we need to define the thermodynamical
alphaOmega1 0.5;
alphaOmega2 0.856; properties of the working fluid and the temperature field (we are also solving the
gamma1 0.55555556;
gamma2 0.44;
Patch where we are computing y+ energy equation).
beta1 0.075;
beta2 0.0828; • Also remember, compressible solvers use absolute pressure. Conversely,
betaStar 0.09;
a1 0.31; incompressible solvers use relative pressure.
b1 1;
c1
F3
10;
false; Minimum, maximum and average values • This case is already setup in the directory
}

Patch 4 named cylinder y+ : min: 0.94230389 max: 12.696632 average: 7.3497345


$PTOFC/101OF/vortex_shedding/c24
Writing yPlus to field yPlus Writing the field to the solution directory

243 244

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• The following dictionaries remain unchanged The constant directory

• In this directory, we will find the following compulsory dictionary files:


• system/blockMeshDict
• constant/polyMesh/boundary
• thermophysicalProperties
• turbulenceProperties

• Reminder:
• thermophysicalProperties contains the definition of the physical
• The diameter of the cylinder is 0.002 m.
properties of the working fluid.
• The working fluid is air at 20° Celsius and at a sea level.
• turbulenceProperties contains the definition of the turbulence model to
• Isothermal flow. use.
• And we are targeting for a Re = 200.

245 246
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The thermophysicalProperties dictionary file The thermophysicalProperties dictionary file

• This dictionary file is located in the directory constant. • In the sub-dictionary mixture (lines 29-46), we define the
18 thermoType Thermophysical models are concerned with energy, heat 18 thermoType thermophysical properties of the working fluid.
19 { 19 {
20 type hePsiThermo; and physical properties. 20 type hePsiThermo;
21 mixture pureMixture; 21 mixture pureMixture;
• In this case, we are defining the properties for air at 20°
22 transport const; • In the sub-dictionary thermoType (lines 18-27), we 22 transport const; Celsius and at a sea level.
23 thermo hConst; 23 thermo hConst;
24 equationOfState perfectGas; define the thermophysical models. 24 equationOfState perfectGas;
25 specie specie; 25 specie specie;
26 energy sensibleEnthalpy; • The transport modeling concerns evaluating dynamic 26 energy sensibleEnthalpy;
27 } 27 }
28 viscosity (line 22). In this case the viscosity is constant. 28
29 mixture 29 mixture
30
31
{
specie
• The thermodynamic models (thermo) are concerned with 30
31
{
specie
32 { evaluating the specific heat Cp (line 23). In this case Cp 32 {
33 nMoles 1; 33 nMoles 1;
34 molWeight 28.9; is constant 34 molWeight 28.9;
35 } 35 }
36 thermodynamics • The equationOfState keyword (line 24) concerns to the 36 thermodynamics
37 { 37 {
38 Cp 1005; equation of state of the working fluid. In this case 38 Cp 1005;
39 Hf 0; 39 Hf 0;
40 } 40 }
41 transport 41 transport
42 { 42 {
43 mu 1.84e-05; 43 mu 1.84e-05;
44 Pr 0.713; 44 Pr 0.713;
45 } • The form of the energy equation to be used in the 45 }
46 } 46 }
solution is specified in line 26 (energy). In this case we
are using enthalpy (sensibleEnthalpy).

247 248

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The turbulenceProperties dictionary file The 0 directory
• In this dictionary file we select what model we would like to use (laminar or
turbulent). • In this directory, we will find the dictionary files that contain the boundary and
initial conditions for all the primitive variables.
• This dictionary is compulsory.
• As we are solving the compressible laminar Navier-Stokes equations, we will
• As we do not want to model turbulence, the dictionary is defined as follows, find the following field files:

• p (pressure)
• T (temperature)
17 simulationType laminar;
• U (velocity field)

249 250
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The file 0/p The file 0/T
• This file contains the boundary and initial conditions 17 dimensions [0 0 0 -1 0 0 0];
• This file contains the boundary and initial conditions
17 dimensions [1 -1 -2 0 0 0 0];
18
for the scalar field pressure (p). We are working 18 for the scalar field temperature (T).
19 internalField uniform 293.15;
19 internalField uniform 101325; with absolute pressure. 20
20 21 boundaryField • Also, pay attention to the units (line 17). The
21
22
boundaryField
{
• Contrary to incompressible flows where we defined 22 { temperature is defined in Kelvin.
23 in
23 in relative pressure, this is the absolute pressure. 24 {
24 { 25 type fixedValue; • We are using uniform initial conditions (line 19).
25 type zeroGradient;
• Also, pay attention to the units (line 17). The 26 value $internalField;
26 } 27 } • For the in patch we are using a fixedValue boundary
28 out pressure is defined in Pascal. 29 out
29 { 30 { condition.
30 type fixedValue;
• We are using uniform initial conditions (line 19). 31 type inletOutlet;
31
32 }
value uniform 101325; 32 value $internalField; • For the out patch we are using a inletOutlet
33 inletValue $internalField;
34 cylinder • For the in patch we are using a zeroGradient 34 } boundary condition (in case of backflow).
35 { 36 cylinder
boundary condition.
36
37 }
type zeroGradient; 37 { • For the cylinder patch we are using a zeroGradient
38 type zeroGradient;
39 sym1 • For the outlet patch we are using a fixedValue 39 } boundary condition.
40 { 41 sym1
boundary condition.
41
42 }
type symmetryPlane; 42 { • The rest of the patches are constrained.
43 type symmetryPlane;
44 sym2 • For the cylinder patch we are using a zeroGradient 44 }
45 { 46 sym2
46 type symmetryPlane; boundary condition. 47 {
47 } 48 type symmetryPlane;
49 back • The rest of the patches are constrained. 49 }
50 { 51 back
51 type empty; 52 {
52 } 53 type empty;
54 front 54 }
55 { 56 front
56 type empty; 57 {
57 } 58 type empty;
58 } 59 }
60 }

251 252

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The file 0/U The system directory
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. • The system directory consists of the following compulsory dictionary files:
21 boundaryField
• We are using uniform initial conditions and the
22
23
{
in
numerical value is (1.5 0 0) (keyword internalField in
• controlDict
24 {
25 type fixedValue; line 19).
26 value uniform (1.5 0 0); • fvSchemes
27
29
}
out
• For the in patch we are using a fixedValue boundary
30
31
{
type inletOutlet;
condition. • fvSolution
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
• For the cylinder patch we are using a zeroGradient
38
39
{
type fixedValue; boundary condition. • controlDict contains general instructions on how to run the case.
40 value uniform (0 0 0);
41 }
43 sym1 • The rest of the patches are constrained. • fvSchemes contains instructions for the discretization schemes that will be
44 {
45 type symmetryPlane;
46 } used for the different terms in the equations.
48 sym2
49 {
50
51 }
type symmetryPlane; • fvSolution contains instructions on how to solve each discretized linear
53
54
back
{ equation system.
55 type empty;
56 }
58 front
59 {
60 type empty;
61 }
62 }

253 254
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The controlDict dictionary The controlDict dictionary

17 application rhoPimpleFoam;
• This case will start from the last saved solution (startFrom). If there is 55 functions • As usual, at the bottom of the controlDict dictionary file
18 no solution, the case will start from time 0 (startTime). 56 { we define the functionObjects (lines 55-236).
19 startFrom startTime;
20 //startFrom latestTime; • It will run up to 0.3 seconds (endTime). 178 forceCoeffs_object
21 179 { • Of special interest is the functionObject
22 startTime 0; • The initial time step of the simulation is 0.00001 seconds (deltaT). 188 type forceCoeffs;
forceCoeffs_object.
23 189 functionObjectLibs ("libforces.so");
24 stopAt endTime; 190 patches (cylinder);
25 //stopAt writeNow;
• It will write the solution every 0.0025 seconds (writeInterval) of 191 • As we changed the domain dimensions and the inlet
26 simulation time (adjustableRunTime). The option adjustableRunTime 192 pName p;
velocity we need to update the reference values (lines 204-
27 endTime 0.3; will adjust the time-step to save the solution at the precise intervals. This 193 Uname U;
28
may add some oscillations in the solution as the CFL is changing.
194 //rhoName rhoInf; 206).
29 deltaT 0.00001; 195 rhoInf 1.205;
30
31 writeControl adjustableRunTime; • It will keep all the solution directories (purgeWrite).
196
197 //// Dump to file
• It is also important to update the reference density (line
32 198 log true; 195).
33 writeInterval 0.0025; • It will save the solution in ascii format (writeFormat). 199
34 200 CofR (0.0 0 0);
35 purgeWrite 0; • And as the option runTimeModifiable is on, we can modify all these 201 liftDir (0 1 0);
36 202 dragDir (1 0 0);
37 writeFormat ascii; entries while we are running the simulation. 203 pitchAxis (0 0 1);
38 204 magUInf 1.5;
39 writePrecision 10; • In line 49 we turn on the option adjustTimeStep. This option will 205 lRef 0.001;
40 automatically adjust the time step to achieve the maximum desired 206 Aref 0.000002;
41 writeCompression off; 207
42 courant number (line 50). 208 outputControl timeStep;
43 timeFormat general; 209 outputInterval 1;
44 • We also set a maximum time step in line 51. 210 }
45 timePrecision 6;
46 • Remember, the first time step of the simulation is done using the value 235
47 runTimeModifiable true;
set in line 28 and then it is automatically scaled to achieve the desired 236 };
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.

255 256

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The fvSchemes dictionary The fvSolution dictionary

17 ddtSchemes • In this case, for time discretization (ddtSchemes) we are 17 solvers • To solve the pressure (p) we are using the PCG method with
18 { using the Euler method. 18 { an absolute tolerance of 1e-6 and a relative tolerance relTol
19 default Euler; 20 p
20 } 21 { of 0.01.
21 • For gradient discretization (gradSchemes) we are using the 22 solver PCG;
22
23
gradSchemes
{
leastSquares method. 23
24
preconditioner
tolerance
DIC;
1e-06;
• The entry pFinal refers to the final correction of the PISO
29 default cellLimited leastSquares 1; 25 relTol 0.01; loop. Notice that we are using macro expansion ($p) to copy
34 } • For the discretization of the convective terms (divSchemes) 26 minIter 2;
35 27 } the entries from the sub-dictionary p.
36 divSchemes
we are using linearUpwind interpolation with no slope limiters 46 pFinal
37 { for the term div(phi,U). 47 { • To solve U and UFinal (U.*) we are using the solver
38 default none; 48 $p;
PBiCGStab with an absolute tolerance of 1e-8 and a relative
39
40
div(phi,U) Gauss linearUpwindV default;
• For the terms div(phi,K) (kinetic energy) and div(phi,h) 49
50
relTol
minIter
0;
2;
tolerance relTol of 0.
41 div(phi,K) Gauss linear; (enthalpy) we are using linear interpolation method with no 51 }
42 div(phi,h) Gauss linear; 53 "U.*"
43 slope limiters. 54 { • To solve hFinal (enthalpy) we are using the solver
44 div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; 55 solver PBiCGStab;
PBiCGStab with an absolute tolerance of 1e-8 and a relative
45 } • For the term div(((rho*nuEff)*dev2(T(grad(U))))) we are 56 preconditioner DILU;
46 57 tolerance 1e-08; tolerance relTol of 0.
47 laplacianSchemes using linear interpolation (this term is related to the turbulence 58 relTol 0;
48
49
{
default Gauss linear limited 1;
modeling). 59
60 }
minIter 2;
• To solve rho and rhoFinal (rho.*) we are using the diagonal
50 } 74 hFinal solver (remember rho is found from the equation of state, so
51 • For the discretization of the Laplacian (laplacianSchemes 75 {
52 interpolationSchemes 76 solver PBiCGStab; this is a back-substitution).
53 {
and snGradSchemes) we are using the Gauss linear limited 77 preconditioner DILU;
54 default linear; 1 method. 78 tolerance 1e-08; • FYI, solving for the velocity is relative inexpensive, whereas
55 } 79 relTol 0;
56 80 minIter 2; solving for the pressure is expensive.
57 snGradSchemes
• This method is second order accurate. 81 }
58 { 83 "rho.*" • Be careful with the enthalpy, it might cause oscillations.
59 default limited 1; 84 {
60 } 85 solver diagonal;
86 }
87 }

257 258
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary Running the case – Using a compressible solver
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c24
88 • The PIMPLE sub-dictionary contains entries related to the
89 PIMPLE pressure-velocity coupling (in this case the PIMPLE method). • Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this case we will use
90 {
91 momentumPredictor yes; blockMesh.
92 nOuterCorrectors 1; • Setting the keyword nOuterCorrectors to 1 is equivalent to
93 nCorrectors 2;
running using the PISO method. • To run this case, in the terminal window type:
94 nNonOrthogonalCorrectors 1;
95 rhoMin 0.5;
96 rhoMax 2.0; • Hereafter we are doing 2 PISO correctors (nCorrectors) and
97 }
1 non-orthogonal corrections (nNonOrthogonalCorrectors). 1. $> foamCleanTutorials
• In lines 95-96 we set the minimum and maximum physical 2. $> blockMesh
values of rho (density).
• If we increase the number of nCorrectors and 3. $> transformPoints –scale ‘(0.001 0.001 0.001)’
nNonOrthogonalCorrectors we gain more stability but at a $> renumberMesh -overwrite
higher computational cost.
4.
• The choice of the number of corrections is driven by the 5. $> rhoPimpleFoam | tee log
quality of the mesh and the physics involve.
$> pyFoamPlotWatcher.py log
• You need to do at least one PISO loop (nCorrectors). 6.
You will need to launch this script in a different terminal

$> gnuplot scripts0/plot_coeffs


7.
You will need to launch this script in a different terminal

8. $> rhoPimpleFoam –postProcess –func MachNo


9. $> paraFoam
259 260

Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
rhoPimpleFoam output screen
Running the case – Using a compressible solver
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


• In step 3 we scale the mesh.
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
• In step 4 we use the utility renumberMesh to make the linear system more diagonal 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
dominant, this will speed-up the linear solvers. 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
• In step 5 we run the simulation and save the log file. Notice that we are sending the rho max/min : 1.201420286 1.201382023
DICPCG: Solving for p, Initial residual = 0.003160602108, Final residual = 9.794177338e-07, No Iterations 69
pFinal

DICPCG: Solving for p, Initial residual = 0.0004558492254, Final residual = 9.278622052e-07, No Iterations 58
job to background. 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

• In step 6 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the rho max/min : 1.201420288 1.201381976
ExecutionTime = 480.88 s ClockTime = 490 s
Max/min density values

job is running in background, we can launch this utility in the same terminal tab. faceSource inMassFlow output:
sum(in) of phi = -7.208447027e-05

• In step 7 we use the gnuplot script scripts0/plot_coeffs to plot the force faceSource outMassFlow output:
sum(out) of phi = 7.208444452e-05
coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to fieldAverage fieldAverage output:
monitor a quantity of interest. Feel free to take a look at the script and to reuse it. Calculating averages

Writing average fields


• In step 8 we use the utility MachNo to compute the Mach number. forceCoeffs forceCoeffs_object output:
Cm = -0.001269886395
Cd = 1.419350733
Cl = 0.6247248606 Force coefficients
Cl(f) = 0.3110925439 Minimum and
Cl(r) = 0.3136323167 maximum values
fieldMinMax minmaxdomain output:
min(p) = 101322.7878 at location (-0.0001215826043 0.001027092827 0)
max(p) = 101326.4972 at location (-0.001033408037 -4.061934599e-05 0)
min(U) = (-0.526856427 -0.09305459972 -8.110485132e-25) at location (0.002039092041 -0.0004058872656 -3.893823418e-20)
max(U) = (2.184751599 0.2867627526 4.83091257e-25) at location (0.0001663574444 0.001404596295 0)
min(T) = 293.1487423 at location (-5.556854517e-05 0.001412635233 0)
261 max(T) = 293.1509903 at location (-0.00117685237 -4.627394552e-05 3.016083257e-20) 262
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• In the directory $PTOFC/101OF/vortex_shedding, you will find 28 variations of the cylinder case involving • This is what you will find in each directory,
different solvers and models. Feel free to explore all them.
• c16 = blockMesh – simpleFoam – Re = 100000 – K-Omega SST turbulent model with no wall functions.
• This is what you will find in each directory,
• c17 = blockMesh – simpleFoam – Re = 100000 – K-Omega SST turbulent model with wall functions.
• c1 = blockMesh – icoFoam – Re = 200.
• c18 = blockMesh – pisoFoam – Re = 100000, LES Smagorinsky turbulent model.
• c2 = fluentMeshToFoam – icoFoam – Re = 200.
• c19 = blockMesh – pimpleFoam – Re = 1000000 – Spalart Allmaras turbulent model with no wall
• c3 = blockMesh – pisoFoam – Field initialization – Re = 200. functions.
• c4 = blockMesh – potentialFoam – Re = 200. • c20 = blockMesh – sonicFoam – Mach = 2.0 – Compressible – Laminar.
• c5 = blockMesh – mapFields – pisoFoam – original mesh – Re = 200. • c21 = blockMesh – sonicFoam – Mach = 2.0 – Compressible – K-Omega SST turbulent model with wall
functions.
• c6 = blockMesh – mapFields – pisoFoam – Finer mesh – Re = 200.
• c22 = blockMesh – pimpleFoam – Re = 200 – No turbulent model – Source terms (momentum)
• c7 = blockMesh – pimpleFoam – Re = 200 – No turbulent model.
• c23 = blockMesh – pimpleFoam – Re = 200 – No turbulent model – Source terms (scalar transport)
• c8 = blockMesh – pisoFoam – Re = 200 – No turbulent model.
• c24 = blockMesh – rhoPimpleFoam – Re = 200 – Laminar, isothermal
• c9 = blockMesh – pisoFoam – Re = 200 – K-Omega SST turbulent model.
• c25 = blockMesh – rhoPimpleFoam – Re = 20000 – Turbulent, compressible
• c10 = blockMesh – simpleFoam – Re = 200 – No turbulent model.
• c26 = blockMesh – pimpleDyMFoam – Re = 200 – Laminar, moving cylinder (oscillating).
• c11 = blockMesh – simpleFoam – Re = 40 – No turbulent model.
• c27 = blockMesh – pimpleDyMFoam/pimpleFoam – Re = 200 – Laminar, rotating cylinder using AMI
• c12 = blockMesh – pisoFoam – Re = 40 – No turbulent model.
patches.
• c14 = blockMesh – pimpleFoam – Re = 10000 – K-Omega SST turbulent model with wall functions.
• c28 = blockMesh – interFoam – Laminar, multiphase, free surface.
• c15 = blockMesh – pimpleFoam – Re = 100000 – K-Omega SST turbulent model with wall functions.
• c29 = blockMesh – pimpleFoam laminar with source terms and AMR.

263 264

Roadmap

Module 2
1. Solid modeling preliminaries and
Solid modeling
introduction to Onshape

265 266
Solid modeling – Preliminaries Solid modeling – Preliminaries
• There is no wrong or right way when doing solid modeling for CFD. The • There are always many ways to accomplish a task when creating a
only rule you should keep in mind is that by the end of the day you should geometry, this give you the freedom to work in a way that is comfortable to
get a smooth, clean, and watertight geometry. you. Hereafter we are going to show you our way.
• A watertight geometry means a close body with no holes or overlapping • Before starting to create your geometry, think about a strategy to employ to
surfaces. create your design, this is what we call design intent.
• Have in mind that the quality of the mesh and hence of the solution, greatly • Choose one feature over other.
depends on the geometry. So always do your best when creating the
• Dimensioning strategy.
geometry.
• Order of the operations.
• 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. • Parametrization.
• The best way to learn how to use these tools is by doing. • 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.

267 268

Solid modeling – Preliminaries Solid modeling – Preliminaries


Geometry defeaturing Geometry defeaturing
• Many times, it is not necessary to model all the details of the geometry. In these cases you
• Would you use all these geometry details for a CFD simulations?
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.

Are the nuts and bolts necessary


in my simulation?

Do we really need to
capture the fillet details?

Do we need to
model the flange?
269 270
Solid modeling using Onshape Solid modeling using Onshape
• Onshape is a professional CAD/solid modeling application. • Even if you have not used a CAD software before, you will find the GUI easy to use.
• It provides powerful parametric and direct modeling capabilities. • You will notice that there is no save button because everything you do is
automatically saved.
• It is cloud based therefore you do not need to install any software. Help
Versioning, branching, and history menu Toolbar
• Documents are shareable.
• Multiple users can work in the same document at the same time Undo/Redo View cube

(simultaneous editing).
• It runs in any device with a working web browser.
• Users can implement their own features using Onshape scripting language Enter to sketch mode

(featureScript).
• Users can access and modify documents in a programmatic way using Feature list

python or nodejs.
• It is freely available for educational use.
• To start using onshape register at: https://cad.onshape.com/ Parts list

3D area
271 Document tabs 272

Solid modeling using Onshape Solid modeling using Onshape


• Mouse interaction in the 3D area (it can be configure in the preference area). • Parametric modeling and feature based modeling are crucial components in the
design experience.
Mouse interaction in the
3D viewer
• In onshape you will find the following features:

Feature toolbar:
Selection

Rotate Sketch toolbar:

Pan
• Remember, sketches are the core of good 3D designs and parametrization.
• This is all we need to know about onshape.
Zoom
• Let us work with a simple geometry to understand how onshape works.
• We also will show you a few clicks and picks you should be aware of.

• To deselect click in an empty region in the 3D area


273 274
Solid modeling using Onshape Solid modeling using Onshape
• Let us create this solid using the dimensions illustrated. • Enter the document page and create a new design

Create new document

Note: all the dimensions are in meters


275 276

Solid modeling using Onshape Solid modeling using Onshape


• In the part studio page, select the top plane and start a new sketch. • In the part studio page, select the top plane and start a new sketch.

2. Start a new sketch

1. Select this plane

Right click on the 3D


area and select view
normal to sketch plane

Part studio page

277 278
Solid modeling using Onshape Solid modeling using Onshape
• Using the sketching features, draw the following line. • Select the right plane and start a new sketch.
When you are done sketching • Draw a circle with the center in the origin (the white point).
press the checkmark
When you are done sketching
press the checkmark

Select this plane and


start a new sketch

Origin

In sketch mode: Use the dimensions illustrated to Use the dimensions illustrated to
• Blue geometry is free to move. draw this polyline draw the circle
• Black geometry is fully defined.
• Red geometry is over-constrained.
279 280

Solid modeling using Onshape Solid modeling using Onshape


• Use the sweep feature to create a new solid. • At this point, you should have this solid.

Select the circle as the Select new solid Select the lines as the
face to sweep sweep patch

Sweep feature

Solid name.
Right click to rename
or view the properties

281 282
Solid modeling using Onshape Solid modeling using Onshape
• Let us add the new inlet to the pipe. • Create a plane normal to a line and passing through a point
• Create a new sketch in the top plane or edit the initial sketch.
• Hereafter we will edit the initial sketch. 1. Create new plane

2. Select point normal,


and select the line and
Right click and choose point as illustrated
the option edit

To get better visibility, you


can hide the solid or adjust Use this line to create
the transparency the new plane

Sketch these new lines using the dimensions illustrated. Use this point to create
Pay attention to the angle and the offset distance. the new plane

283 284

Solid modeling using Onshape Solid modeling using Onshape


• Sketch a circle in the newly created plane. • 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

New plane Use this sketch as the


base for the extrusion
Extrusion.
You can manually move
To get better visibility, you the extrusion using the
can hide the solid or adjust triad manipulator, or
the transparency input a value

Sketch this circle in the newly created plane Instead of the extrusion feature, you could use
the sweep feature. You will need to create a
longer sweep path.
285 286
Solid modeling using Onshape Solid modeling using Onshape
• At this point you should have the following solid. • 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.

Select the part.


Right click and select
assign material.

Mass properties icon

287 288

Solid modeling using Onshape Solid modeling using Onshape


• To export the solid model, right click on the part name and select the option export. • Parametric modeling and feature-based modeling are two of the most powerful tools
• Choose the desired format. In this case choose STL. 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
Right click and select the
videos in the context of CFD and OpenFOAM® :
option export.
https://www.youtube.com/channel/UCNNBm3KxVS1rGeCVUU1p61g

289 290
Before we begin
• OpenFOAM® comes with the following meshing applications:
• blockMesh
• snappyHexMesh
• foamyHexMesh

Module 3 •
• foamyQuadMesh
We are going to work with blockMesh and snappyHexMesh.

Meshing preliminaries – Mesh quality •
blockMesh is a multi-block mesh generator.
snappyHexMesh is an automatic split hex mesher, refines and snaps to surface.
assessment – Meshing in OpenFOAM® • 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®.

291 292

Before we begin Roadmap


By the end of this module, you will realize that
You will use snappyHexMesh to mesh the sphinx
1. Meshing preliminaries
2. What is a good mesh?
You will use blockMesh to mesh the pyramids
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

293 294
Meshing preliminaries Meshing preliminaries
• Mesh generation or domain discretization consist in dividing the physical Mesh generation process
domain into a finite number of discrete regions, called control volumes or
cells in which the solution is sought • 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.
• Remember this: Geometry is to mesh generation as turbulence modeling is
to CFD.
www.wolfdynamics.com/wiki/moving/ani1.gif www.wolfdynamics.com/wiki/moving/ani2.gif
295 296

Meshing preliminaries Meshing preliminaries


Geometry generation - Input geometry Mesh generation
• The geometry must be watertight. • If we are interested in external aerodynamics, we define a physical domain and we mesh the region around
the body.
• 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. • 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.

297 298
Meshing preliminaries Meshing preliminaries
Definition of boundary surfaces (patches) What cell type should I use?
• 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.

http://www.wolfdynamics.com/wiki/cells/ani_tetra.gif http://www.wolfdynamics.com/wiki/cells/ani_hexa.gif http://www.wolfdynamics.com/wiki/cells/ani_poly.gif

inlet outlet • In the meshing world, there are many cell types. Just to name a few: tetrahedrons,
pyramids, hexahedrons, prisms, polyhedral.
top • 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
left right
conditions.
• However, this does not mean that tetra/poly cells are not good.
airplane • 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
bottom 299 300

Roadmap 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
1. Meshing preliminaries practices.
• A standard rule of thumb is that the elements shape and distribution should be
2. What is a good mesh? pleasing to the eye.

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
22rd IMR Meshing Maestro Contest Winner
Travis Carrigan, John Chawner and Carolyn Woeber. Pointwise.
http://imr.sandia.gov/22imr/MeshingContest.html

301 302
What is a good mesh? What is a good mesh?
• The user can rely on grid dependency studies, but they are time consuming and • Finally, we can rely in mesh metrics. However, no single standard
expensive. benchmark or metric exists that can effectively assess the quality of a
mesh, but the user can rely on suggested best practices.
Coarse mesh Medium mesh Fine mesh Extra fine mesh
• Hereafter, we will present the most common mesh quality metrics:
Cells ≈ 3 500 000 ≈ 11 000 000 ≈ 36 000 000 ≈ 105 000 000 • Orthogonality.
• Skewness.
0.0282 0.0270 0.0268 0.0269
• Aspect Ratio.
-0.0488 -0.0451 -0.0391 -0.0391 • Smoothness.

• After generating the mesh, we measure these quality metrics and we use
them to assess 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.
Results from AIAA CFD Drag Prediction Workshop

303 304

What is a good mesh? What is a good mesh?


Mesh quality metrics. Mesh orthogonality Mesh quality metrics. Mesh skewness
• Mesh orthogonality is the angular deviation of the vector S (located at the face center • Skewness (also known as non-conjunctionality) is the deviation of the vector d that
f ) from the vector d connecting the two cell centers P and N. In this case is . connects the two cells P and N, from the face center f.
• Affects the gradient of the face center f. • The deviation vector is represented with and is the point where the vector d
• It adds numerical diffusion to the solution. intersects the face f .

• It mainly affects the diffusive terms. • Affects the interpolation of the cell centered quantities to the face center f.
• It adds numerical diffusion and wiggles to the solution.
• It affects the convective and diffusive terms.

305 306
What is a good mesh? What is a good mesh?
Mesh quality metrics. Mesh aspect ratio AR Mesh quality metrics. Smoothness
• Mesh aspect ratio AR is the ratio between the longest side and the shortest • Smoothness, also known as expansion rate, growth factor or uniformity, defines the
side . transition in size between contiguous cells.
• Large AR are ok if gradients in the largest direction are small. • Large transition ratios between cells add diffusion to the solution.
• High AR smear gradients. • Ideally, the maximum change in mesh spacing should be less than 20%:

307 Steep transition Smooth transition 308

What is a good mesh? What is a good mesh?


Mesh quality metrics. Element type close to the walls - Cell/Flow alignment
Striving for quality
• Hexes, prisms, and quadrilaterals can be stretched easily to resolve boundary layers
• For the same cell count, hexahedral meshes will give more accurate solutions,
without losing quality.
especially if the grid lines are aligned with the flow.
• Triangular and tetrahedral meshes have inherently larger truncation error. • But this does not mean that tetrahedral meshes are not good, by carefully choosing
• Less truncation error when faces aligned with flow direction and gradients. 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.

Flow direction
• In the early years of CFD, there was a huge
Tetra gap between the outcome of tetra and hex
meshes.
• But with time and thanks to developments in
numerical methods and computer science
QOI

(software and hardware), today all cell types


give the same results.

Hexa

309 Year 310


What is a good mesh? What is a good mesh?
Striving for quality Striving for quality
• The mesh density should be high enough to capture all relevant flow features. • Hexes, prisms, and quadrilaterals can be easily aligned with the flow.
• They can also be stretched to resolve boundary layers without losing much quality.
• In areas where the solution change slowly, you can use larger elements. • Triangular and tetrahedral meshes can easily be adapted to any kind of geometry. The mesh generation process is almost
automatic.
• A good mesh does not rely in the fact that the more cells we use the better the • Tetrahedral meshes normally need more computing resources during the solution stage. But this can be easily offset by the time
solution. saved during the mesh generation stage.
• Increasing the cells count will likely improve the solution accuracy, but at the cost of a higher computational cost. However, a
finer mesh does not mean a better mesh.
• To keep cell count low, use non-uniform meshes to cluster cells only where they are needed. Use local refinements and solution
adaption to further refine only on selected areas.
• In boundary layers, quads, hexes, and prisms/wedges cells are preferred over triangles, tetrahedrons, or pyramids.
• If you are not using wall functions (turbulence modeling), the mesh next to the walls should be fine enough to resolve the
boundary layer flow. Have in mind that this will rocket the cell count and increase the computing time.
• 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.
23rd IMR Meshing Maestro Contest Winner • So, as long as your results are physically realistic, reliable and accurate; your mesh is good.
Zhoufang Xiao , Jianjing Zheng, Dawei Zhao, Lijuan Zeng, Jianjun Chen, Yao Zheng
Center for Engineering & Scientific Computation, Zhejiang University, China. • Know your physics and generate a mesh able to resolve the physics involve, without over-doing.
http://www.sandia.gov/imr/MeshingContest.html 311 312

What is a good mesh? Roadmap

A good mesh might not lead to the ideal solution, but a bad 1. Meshing preliminaries
mesh will always lead to a bad solution.
P. Baker – Pointwise 2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM®
Who owns the mesh, owns the solution. 4. Mesh generation using blockMesh.
H. Jasak – Wikki Ltd. 5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
Avoid the GIGO syndrome (Garbage In – Garbage Out). 7. Mesh conversion
As I am a really positive guy I prefer to say,
8. Geometry and mesh manipulation utilities
good mesh – good results.
J. G – WD

313 314
Mesh quality assessment in OpenFOAM® Mesh quality assessment in OpenFOAM®
Mesh quality metrics in OpenFOAM® Checking the mesh quality in OpenFOAM®
• In the file primitiveMeshCheck.C located in the directory • To check the mesh quality and validity, OpenFOAM® comes with the utility checkMesh.
$WM_PROJECT_DIR/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/ you will find the
• To use this utility, just type in the terminal checkMesh, and read the screen output.
quality metrics hardwired in OpenFOAM®. Their maximum (or minimum) values are defined as follows:
• checkMesh will look for/check for:
• Mesh stats and overall number of cells of each type.
36 Foam::scalar Foam::primitiveMesh::closedThreshold_ = 1.0e-6;
• Check topology (boundary conditions definitions).
37 Foam::scalar Foam::primitiveMesh::aspectThreshold_ = 1000;
• Check geometry and mesh quality (bounding box, cell volumes, skewness, orthogonality, aspect
38 Foam::scalar Foam::primitiveMesh::nonOrthThreshold_ = 70; // deg
ratio, and so on).
39 Foam::scalar Foam::primitiveMesh::skewThreshold_ = 4;
40 Foam::scalar Foam::primitiveMesh::planarCosAngle_ = 1.0e-6;
• 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.
• You will be able to run simulations with mesh quality errors such as high skewness, high aspect ratio, and high • These sets are saved in the directory constant/polyMesh/sets/
non-orthogonality. But remember, they will affect the solution accuracy, might give you strange results, and • Mesh topology and patch topology errors must be repaired.
eventually can made the solver blow-up.
• You will be able to run with mesh quality errors such as skewness, aspect ratio, minimum face area, and non-
• Have in mind that if you have bad quality meshes, you will need to adapt the numerics to deal with this kind of orthogonality.
meshes. We will give you our recipe later when we deal with the numerics.
• But remember, they will severely tamper the solution accuracy, might give you strange results, and eventually
• You should avoid as much as possible non-orthogonality values close to 90. This is an indication that you have can made the solver blow-up.
zero-volume cells.
• Unfortunately, checkMesh does not repair these errors.
• 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). • You will need to check the geometry for possible errors and generate a new mesh.
• You can visualize the failed sets directly in paraFoam .
• 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 a non-orthogonality up to 80 and skewness up to 8. • Alternatively, you can use the utility foamToVTK to convert the failed sets to VTK format.
315 316

Mesh quality assessment in OpenFOAM® Mesh quality assessment in OpenFOAM®


Visualizing the failed sets in OpenFOAM® Visualizing the failed sets in OpenFOAM®
• To convert the failed faces/cells/points to VTK format, you can proceed as follows:
• You can load the failed sets directly within
paraFoam.
• $> foamToVTK -set_type name_of_sets
• Remember, you will need to create the sets. To
do so just run the checkMesh utility.
• If there are problems in the mesh, checkMesh where set_type is the type of sets (faceSet, cellSet, pointSet, surfaceFields) and
will automatically save the sets in the directory name_of_sets is the name of the set in the directory constant/polyMesh/sets
constant/polyMesh/sets (highAspectRatioCells, nonOrthoFaces, wrongOrientedFaces, skewFaces,
• In paraFoam, simply select the option Include unusedPoints, and so on).
Sets and then select the sets you want to • At the end, foamToVTK will create a directory named VTK, where you will find the
visualize. failed faces/cells/points in VTK format.
• This method only works with paraFoam. • At this point you can use paraview/paraFoam to open the VTK files and visualize
• When working with large meshes we prefer to the failed sets.
convert the faulty sets to VTK format using
foamToVTK. Failed sets

317 318
Mesh quality assessment in OpenFOAM® Mesh quality assessment in OpenFOAM®
Checking mesh quality in OpenFOAM® Checking mesh quality in OpenFOAM®
• Sample checkMesh output, • Sample checkMesh output,
Checking patch topology for multiply connected surfaces...
Patch Faces Points Surface topology
Mesh stats FAIRING 1267 727 ok (non-closed singly connected)
points: 81812 FUSELAGE 3243 1774 ok (non-closed singly connected)
faces: 902132 WING 15313 7706 ok (non-closed singly connected)
internal faces: 871012 INLET 272 160 ok (non-closed singly connected)
cells: 443286 OUTLET 272 160 ok (non-closed singly connected)
Mesh stats Boundary patches
faces per cell: 4 SYMM 6280 3324 ok (non-closed singly connected)
boundary patches: 9 FARFIELD 3136 1645 ok (non-closed singly connected)
point zones: 0 NOSE 76 49 ok (non-closed singly connected)
face zones: 1 COCKPIT 1261 670 ok (non-closed singly connected)
cell zones: 1
Checking geometry...
Overall number of cells of each type: Overall domain bounding box (-15000 -7621.0713 -7396.4536) (30048.969 0 7446.8442)
hexahedra: 0 Mesh has 3 geometric (non-empty/wedge) directions (1 1 1)
prisms: 0 Mesh has 3 solution (non-empty) directions (1 1 1)
wedges: 0 Boundary openness (-4.2298633e-18 8.0240802e-16 4.013988e-16) OK.
Mesh bounding box
pyramids: 0 Number of each type of cells Max cell openness = 4.8098963e-16 OK.
tet wedges: 0 Max aspect ratio = 29.575835 OK. Aspect ratio
tetrahedra: 443286 Minimum face area = 0.0066721253. Maximum face area = 1037224.8. Face area magnitudes OK.
polyhedra: 0 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
Checking topology... *Number of severely non-orthogonal (> 70 degrees) faces: 3168. But we still can run the simulation
Boundary definition OK. Checking mesh topology
Non-orthogonality check OK.
Cell to face addressing OK. <<Writing 3168 non-orthogonal faces to set nonOrthoFaces
***Unused points found in the mesh, number unused by faces: 16 number unused by cells: 16 Face pyramids OK.
<<Writing 16 unused points to set unusedPoints Max skewness = 2.5719979 OK. Skewness
Upper triangular ordering OK. Coupled point location match (average 0) OK.
Face vertices OK.
Number of regions: 1 (OK). Unused points found in the mesh
In this case they do not harm the solution Failed 1 mesh checks. The fact that one check failed does not mean that you can not run the simulation
They can be removed using topoSet and subsetMesh
319 End 320

Mesh quality assessment in OpenFOAM® Roadmap


Visualization of faulty sets in paraFoam
• You will find this case ready to use in the directory,
$PTOFC/mesh_quality_manipulation/M1_wingbody 1. Meshing preliminaries
• To run the case, just follow the instructions in the README.FIRST files.
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

Non orthogonal faces (green spheres) and unused points (yellow spheres) 321 322
Mesh generation using blockMesh Mesh generation using blockMesh
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.
• The 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 v
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. v

323 324

Mesh generation using blockMesh blockMesh guided tutorials


blockMesh workflow
• Meshing with blockMesh – Case 1.
• We will use the square cavity case.
• You will find this case in the directory:

$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.
• To generate a mesh with blockMesh, you will need to define the vertices, block
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
connectivity and number of cells in each direction. way, you will get used with the command line interface and OpenFOAM® commands.
• To assign boundary patches, you will need to define the faces connectivity • If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
325 326
blockMesh guided tutorials blockMesh guided tutorials
What are we going to do? The blockMeshDict dictionary.
• We will use this simple case to take a close look at a blockMeshDict dictionary. • The keyword convertToMeters (line 17), is a scaling
17 convertToMeters 1; factor. In this case we do not scale the dimensions.
• We will study all sections in the blockMeshDict dictionary. 18
19 xmin 0;
20 xmax 1; • In lines 19-24 we declare some variables using macro
21 ymin 0;
• We will introduce two features useful for parameterization, namely, macro syntax and 22 ymax 1;
syntax notation. With macro syntax, we first declare the
23 zmin 0; variables and their values (lines 19-24), and then we can
inline calculations. 24 zmax 1;
use the variables by adding the symbol $ to the variable
25
30 deltax 0.05; name (lines 47-54).
• You can use this dictionary as a blockMeshDict template that you can change 31 deltay 0.05;
32 deltaz 0.05;
automatically according to the dimensions of your domain and the desired cell 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.
spacing. 35
36
ly #calc "$ymax - $ymin";
lz #calc "$zmax – $zmin";
37 • Macro syntax is a very convenient way to parameterize
38 xcells #calc "round($lx/$deltax)"; dictionaries.
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 );

327 328

blockMesh guided tutorials blockMesh guided tutorials


The blockMeshDict dictionary. The blockMeshDict dictionary.
• In lines 34-40 we are doing inline calculations using the • To do inline calculations using the directive #calc, we
17 convertToMeters 1; directive #calc. 17 convertToMeters 1; proceed as follows (we will use line 35 as example):
18 18
19 xmin 0; 19 xmin 0;
20 xmax 1; • Basically we are programming directly in the dictionary. 20 xmax 1;
21 ymin 0; OpenFOAM® will compile this function as it reads it. 21 ymin 0;
22 ymax 1; 22 ymax 1; ly #calc "$ymax - $ymin";
23 zmin 0; 23 zmin 0;
24 zmax 1; • With inline calculations and codeStream you can access 24 zmax 1;
25 many OpenFOAM® functions from the dictionaries. 25
30 deltax 0.05; 30 deltax 0.05;
31 deltay 0.05; 31 deltay 0.05; • We first give a name to the new variable (ly), we then tell
32 deltaz 0.05; • Inline calculations and codeStream are very convenient 32 deltaz 0.05;
33 33
OpenFOAM® that we want to do an inline calculation
ways to parameterize dictionaries and program directly
34 lx #calc "$xmax - $xmin"; 34 lx #calc "$xmax - $xmin"; (#calc), and then we do the inline calculation ("$ymax-
35 ly #calc "$ymax - $ymin"; on the dictionaries. 35 ly #calc "$ymax - $ymin";
36 lz #calc "$zmax – $zmin"; 36 lz #calc "$zmax – $zmin"; $ymin";). Notice that the operation must be between
37 37
38 xcells #calc "round($lx/$deltax)"; 38 xcells #calc "round($lx/$deltax)";
double quotation marks.
39 ycells #calc "round($ly/$deltay)"; 39 ycells #calc "round($ly/$deltay)";
40 zcells #calc "round($lz/$deltaz)"; 40 zcells #calc "round($lz/$deltaz)";
41 41
44 vertices 44 vertices
45 ( 45 (
46 //BLOCK 0 46 //BLOCK 0
47 ($xmin $ymin $zmin) //0 47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1 48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2 49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3 50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4 51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5 52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6 53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7 54 ($xmin $ymax $zmax) //7
66 ); 66 );

329 330
blockMesh guided tutorials blockMesh guided tutorials
The blockMeshDict dictionary. The blockMeshDict dictionary.
• In lines lines 34-36, we use inline calculations to • By the way, as this dictionary is designed for blocks with
17 convertToMeters 1; compute the length in each direction. 17 convertToMeters 1; positive vertices coordinates, there is a small catch in the
18 18
19 xmin 0; 19 xmin 0; way we compute the length (lines 34-36) and the number
20 xmax 1; • Then we compute the number of cells to be used in each 20 xmax 1;
21 ymin 0; 21 ymin 0;
of cells (lines 38-40).
22 ymax 1;
direction (lines 38-40). 22 ymax 1;
23 zmin 0; 23 zmin 0; • What will happen if xmin is negative?
24 zmax 1; • To compute the number of cells we use as cell spacing 24 zmax 1;
25
30 deltax 0.05;
the values declared in lines 30-32. 25
30 deltax 0.05;
• What will happen if xcells is negative?
31 deltay 0.05; 31 deltay 0.05;
32 deltaz 0.05; • By proceeding in this way, we can compute automatically 32 deltaz 0.05; • What will happen if xcells is a float with decimals?
33 33
the number of cells needed in each direction according to
34 lx #calc "$xmax - $xmin"; 34 lx #calc "$xmax - $xmin"; • Can you find a solution to these small problems?
35 ly #calc "$ymax - $ymin"; the desired cell spacing. 35 ly #calc "$ymax - $ymin";
36 lz #calc "$zmax – $zmin"; 36 lz #calc "$zmax – $zmin";
37 37
38 xcells #calc "round($lx/$deltax)"; 38 xcells #calc "round($lx/$deltax)";
39 ycells #calc "round($ly/$deltay)"; 39 ycells #calc "round($ly/$deltay)";
40 zcells #calc "round($lz/$deltaz)"; 40 zcells #calc "round($lz/$deltaz)";
41 41
44 vertices 44 vertices
45 ( 45 (
46 //BLOCK 0 46 //BLOCK 0
47 ($xmin $ymin $zmin) //0 47 ($xmin $ymin $zmin) //0
48 ($xmax $ymin $zmin) //1 48 ($xmax $ymin $zmin) //1
49 ($xmax $ymax $zmin) //2 49 ($xmax $ymax $zmin) //2
50 ($xmin $ymax $zmin) //3 50 ($xmin $ymax $zmin) //3
51 ($xmin $ymin $zmax) //4 51 ($xmin $ymin $zmax) //4
52 ($xmax $ymin $zmax) //5 52 ($xmax $ymin $zmax) //5
53 ($xmax $ymax $zmax) //6 53 ($xmax $ymax $zmax) //6
54 ($xmin $ymax $zmax) //7 54 ($xmin $ymax $zmax) //7
66 ); 66 );

331 332

blockMesh guided tutorials blockMesh guided tutorials


The blockMeshDict dictionary. The blockMeshDict dictionary.
• In the vertices section (lines 44-66), we define the vertex • In lines 68-71, we define the block topology, hex means that it is a structured hexahedral block. In this case,
17 convertToMeters 1; coordinates of the geometry. we are generating a rectangular mesh.
18
19 xmin 0;
20 xmax 1; • In this case, there are eight vertices defining a 3D block. • 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
21 ymin 0;
22 ymax 1; • Remember, OpenFOAM® always uses 3D meshes, even hex block is defined by eight vertices, in sequential order. Where the first vertex in the list represents the
23 zmin 0;
24 zmax 1; if the simulation is 2D. For 2D meshes, you only add one origin of the coordinate system (vertex 0 in this case).
25 cell in the third dimension.
30 deltax 0.05; • ($xcells $ycells $zcells) is the number of mesh cells in each direction (X Y Z). Notice that we are using
31 deltay 0.05;
32 deltaz 0.05; • Notice that the vertex numbering starts from 0 (as the macro syntax, and we compute the values using inline calculations.
33
34 lx #calc "$xmax - $xmin";
counters in c++). This numbering applies for blocks as • simpleGrading (1 1 1) is the grading or mesh stretching in each direction (X Y Z), in this case the mesh is
35 ly #calc "$ymax - $ymin"; well. uniform. We will deal with mesh grading/stretching in the next case.
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 68 blocks
47 ($xmin $ymin $zmin) //0 69 (
48 ($xmax $ymin $zmin) //1 70 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
49 ($xmax $ymax $zmin) //2 71 );
50 ($xmin $ymax $zmin) //3 72
51 ($xmin $ymin $zmax) //4 73 edges
52 ($xmax $ymin $zmax) //5 74 (
53 ($xmax $ymax $zmax) //6 75
54 ($xmin $ymax $zmax) //7 76 );
66 );

333 334
blockMesh guided tutorials blockMesh guided tutorials
The blockMeshDict dictionary. The blockMeshDict dictionary.
• Let us talk about the block ordering hex (0 1 2 3 4 5 6 7), which is extremely important. • Edges, are constructed from the vertices definition.
• hex blocks are defined by eight vertices in sequential order. Where the first vertex in the list represents the • Each edge joining two vertices is assumed to be straight by default.
origin of the coordinate system (vertex 0 in this case).
• The user can specified any edge to be curved by entries in the section edges.
• Starting from this vertex, we construct the block topology. So in this case, the first part of the block is made up
• Possible options are: arc, spline, polyline, BSpline, line.
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). • 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.
• 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. • 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.
• 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 might need to merges faces, we will address this later. • In this case and as we do not specified anything, all edges are assumed to be straight lines.

68 blocks 68 blocks
69 ( 69 (
70 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1) 70 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
71 ); 71 );
72 72
73 edges 73 edges
74 ( 74 (
75 75
76 ); 76 );

335 336

blockMesh guided tutorials blockMesh guided tutorials


The blockMeshDict dictionary. The blockMeshDict dictionary.
• In the section boundary, we define all the patches where • In lines 80-87 we define a boundary patch.
78 boundary we want to apply boundary conditions. 78 boundary
79 ( 79 ( • In line 80 we define the patch name top (the name is
80 top 80 top
81 { • This step is of paramount importance, because if we do 81 { given by the user).
82 type wall; not define the surface patches we will not be able to 82 type wall;
83 faces 83 faces • In line 82 we give a base type to the surface patch. In
84 ( apply the boundary conditions to individual surface 84 (
85 (3 7 6 2) 85 (3 7 6 2) this case wall (do not worry we are going to talk about
86 );
patches. 86 );
87 } 87 }
this later).
88 left 88 left
89 { 89 { • In line 85 we give the connectivity list of the vertices that
90 type wall; 90 type wall;
91 faces 91 faces
made up the surface patch or face, that is, (3 7 6 2).
92 ( 92 (
93 (0 4 7 3) 93 (0 4 7 3) • Have in mind that the vertices need to be neighbors and
94 ); 94 );
95 } 95 }
it does not matter if the ordering is clockwise or counter
96 right 96 right clockwise.
97 { 97 {
98 type wall; 98 type wall;
99 faces 99 faces
100 ( 100 (
101 (2 6 5 1) 101 (2 6 5 1)
102 ); 102 );
103 } 103 }
104 bottom 104 bottom
105 { 105 {
106 type wall; 106 type wall;
107 faces 107 faces
108 ( 108 (
109 (0 1 5 4) 109 (0 1 5 4)
110 ); 110 );
111 } 111 }

337 338
blockMesh guided tutorials blockMesh guided tutorials
The blockMeshDict dictionary. The blockMeshDict dictionary.
• Have in mind that the vertices need to be neighbors and • In lines 112-119 we define the patch front.
78 boundary it does not matter if the ordering is clockwise or counter 112 front
79 ( 113 { • In lines 120-127 we define the patch back.
80 top clockwise. 114 type wall;
81 { 115 faces
• You can also group many faces into one patch, for
82 type wall; • Remember, faces are defined by a list of 4 vertex 116 (
83 faces 117 (4 5 6 7) example, instead of creating the patches front and back,
84 ( numbers, e.g., (3 7 6 2). 118 );
85 (3 7 6 2) 119 } you can group them into a single patch named
86
87 }
); • In lines 88-95 we define the patch left. 120
121
back
{
backAndFront, as follows,
88 left 122 type wall;
89 { • In lines 96-103 we define the patch right. 123 faces
90 type wall; 124 (
91 faces • In lines 104-11 we define the patch bottom. 125 (0 3 2 1) backAndFront
92 ( 126 ); {
93 (0 4 7 3) 127 }
94 ); 128 ); type wall;
95 } 129 faces
96 right 130 mergePatchPairs
97 { 131 ( (
98 type wall; 132 (4 5 6 7)
99 faces 133 );
100 ( (0 3 2 1)
101 (2 6 5 1) );
102 );
103 } }
104 bottom
105 {
106 type wall;
107 faces
108 (
109 (0 1 5 4)
110 );
111 }

339 340

blockMesh guided tutorials blockMesh guided tutorials


The blockMeshDict dictionary. The blockMeshDict dictionary.
• We can merge blocks in the section mergePatchPairs
112 front (lines 130-133). • To sum up, the blockMeshDict dictionary
113 {
114 type wall;
• The block patches to be merged must be first defined in generates a single block with:
115 faces
116 ( the boundary list, blockMesh then connect the two
117 (4 5 6 7) • X/Y/Z dimensions: 1.0/1.0/1.0
118 ); blocks.
119 }
120 back • In this case, as we have one single block there is no • As the cell spacing in all directions is
121 {
122 type wall; need to merge patches. defined as 0.05, it will use the following
123 faces number of cells in the X, Y and Z directions:
124 (
125 (0 3 2 1) 20 x 20 x 20 cells.
126 );
127 }
128 );
• One single hex block with straight lines.
129
130
131
mergePatchPairs
(
• Six patches of base type wall, namely, left,
132 right, top, bottom, front and back.
133 );

• The information regarding the patch base type


and patch name is saved in the file boundary.
Feel free to modify this file to fit your needs.
• Remember to use the utility checkMesh to check
the quality of the mesh and look for topological
errors.

• Topological errors must be repaired.

341 342
blockMesh guided tutorials blockMesh guided tutorials
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary
18
19
6
(
• First at all, this file is automatically generated after you 18
19
6
(
• If you do not define the boundary patches in the dictionary
20 top create the mesh or you convert it from a third party format. 20 top blockMeshDict, they are grouped automatically in a default
21 { 21 {
22 type wall; 22 type wall; group named defaultFaces of type empty.
23 inGroups 1(wall); • In this file, the geometrical information related to the base 23 inGroups 1(wall);
24
25
nFaces
startFace
400;
22800; type patch of each boundary of the domain is specified.
24
25
nFaces
startFace
400;
22800;
• For instance, if you do not assign a base type to the patch
26 } 26 } front, it will be grouped as follows:
27 left 27 left
28 { • The base type boundary condition is the actual surface 28 {
29 type wall; 29 type wall;
30 inGroups 1(wall); patch where we are going to apply a primitive type 30 inGroups 1(wall);
31 nFaces 400; 31 nFaces 400;
defaultFaces
32 startFace 23200;
boundary condition (or numerical boundary condition). 32 startFace 23200; {
33 } 33 } type empty;
34
35
right
{
• The primitive type boundary condition assign a field value 34
35
right
{
inGroups 1(empty);
nFaces 400;
36 type empty; to the surface patch. 36 type empty;
startFace 24800;
37 inGroups 1(wall); 37 inGroups 1(wall);
38 nFaces 400; 38 nFaces 400; }
39 startFace 23600; • You define the numerical type patch (or the value of the 39 startFace 23600;
40 } 40 }
41 bottom boundary condition), in the directory 0 or time directories. 41 bottom
42 { 42 {
43 type wall; 43 type wall; • Remember, you can manually change the name and type.
44 inGroups 1(wall); • The name and base type of the patches was defined in the 44 inGroups 1(wall);
45 nFaces 400; 45 nFaces 400;
46 startFace 24000;
dictionary blockMeshDict in the section boundary. 46 startFace 24000;
47 } 47 }
48 front 48 front
49 { • You can change the name if you do not like it. Do not use 49 {
50 type wall; strange symbols or white spaces. 50 type wall;
51 inGroups 1(wall); 51 inGroups 1(wall);
52 nFaces 400; 52 nFaces 400;
53
54 }
startFace 24400; • You can also change the base type. For instance, you can 53
54 }
startFace 24400;

55 back change the type of the patch top from wall to patch. 55 back
56 { 56 {
57 type empty; 57 type empty;
58 inGroups 1(wall); 58 inGroups 1(wall);
59 nFaces 400; 59 nFaces 400;
60 startFace 24800; 60 startFace 24800;
61 } 61 }
62 ) 343 62 ) 344

blockMesh guided tutorials blockMesh guided tutorials


The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary
18 6 18 6
19 (
Number of surface patches 19 (
20 top 20 top
21 { 21 {
22 type wall; In the list bellow there must be 6 patches 22 type wall; Name and type of the surface patches
23 inGroups 1(wall); 23 inGroups 1(wall);
24 nFaces 400; definition. 24 nFaces 400;
25 startFace 22800; 25 startFace 22800;
26 } 26 } • The name and base type of the patch is given
27 left 27 left
28 { 28 { by the user.
29 type wall; 29 type wall;
top
30
31
inGroups
nFaces
1(wall);
400;
30
31
inGroups
nFaces
1(wall);
400;
• In this case the name and base type was
32 startFace 23200; 32 startFace 23200; assigned in the dictionary blockMeshDict.
33 } 33 }
34 right 34 right
35 { 35 { • You can change the name if you do not like it.
36 type empty; 36 type wall;
37 inGroups 1(wall); back 37 inGroups 1(wall);
Do not use strange symbols or white spaces.
38 nFaces 400; 38 nFaces 400;
39 startFace 23600; 39 startFace 23600; • You can also change the base type. For
40 } 40 }
41 bottom 41 bottom instance, you can change the type of the
42 { 42 {
43 type wall; 43 type wall;
patch top from wall to patch.
44 inGroups 1(wall); 44 inGroups 1(wall);
45 nFaces 400; left right 45 nFaces 400;
46 startFace 24000; 46 startFace 24000;
47 } 47 }
48 front 48 front
49 { 49 {
50 type wall; 50 type wall;
51 inGroups 1(wall); 51 inGroups 1(wall);
52 nFaces 400; front 52 nFaces 400;
53 startFace 24400; 53 startFace 24400;
54 } 54 }
55 back 55 back
56 { 56 {
57 type empty; 57 type wall;
58 inGroups 1(wall); 58 inGroups 1(wall);
59 nFaces 400; bottom 59 nFaces 400;
60 startFace 24800; 60 startFace 24800;
61 } 61 }
62 ) 345 62 ) 346
blockMesh guided tutorials blockMesh guided tutorials
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary
18 6 18 6
19 ( 19 (
20 top 20 top
21 { 21 {
22 type wall; inGroups keyword 22 type wall; nFaces and startFace keywords
23 inGroups 1(wall); 23 inGroups 1(wall);
24 nFaces 400; 24 nFaces 400;
25 startFace 22800; 25 startFace 22800;
26 } • This is optional. 26 } • Unless you know what you are doing, you do
27 left 27 left
not need to change this information.
28
29
{
type wall; • You can erase this information safely. 28
29
{
type wall;
30 inGroups 1(wall); 30 inGroups 1(wall); • Basically, this is telling you the starting face
31 nFaces 400; • It is used to group patches during visualization 31 nFaces 400;
32 startFace 23200; 32 startFace 23200; and ending face of the patch.
33 } in ParaView/paraFoam. If you open this mesh 33 }
34 right 34 right
35 { in paraFoam you will see that there are two 35 { • This information is created automatically when
36 type wall; 36 type wall;
37 inGroups 1(wall);
groups, namely: wall and empty. 37 inGroups 1(wall);
generating the mesh or converting the mesh.
38 nFaces 400; 38 nFaces 400;
39 startFace 23600; • As usual, you can change the name. 39 startFace 23600;
40 } 40 }
41
42
bottom
{ • If you want to put a surface patch in two 41
42
bottom
{
43
44
type
inGroups
wall;
1(wall);
groups, you can proceed as follows: 43
44
type
inGroups
wall;
1(wall);
45 nFaces 400; 45 nFaces 400;
46 startFace 24000; 2(wall wall1) 46 startFace 24000;
47 } 47 }
48 front 48 front
49 {
In this case the surface patch belongs to the 49 {
50
51
type
inGroups
wall;
1(wall);
group wall (which can have another patch) 50
51
type
inGroups
wall;
1(wall);
52 nFaces 400; and the group wall1 52 nFaces 400;
53 startFace 24400; 53 startFace 24400;
54 } 54 }
55 back 55 back
56 { 56 {
57 type wall; 57 type wall;
58 inGroups 1(wall); 58 inGroups 1(wall);
59 nFaces 400; 59 nFaces 400;
60 startFace 24800; 60 startFace 24800;
61 } 61 }
62 ) 347 62 ) 348

blockMesh guided tutorials blockMesh guided tutorials


Running the case Final remarks on blockMesh
• For the moment, we will limit the use of blockMesh to single-block mesh topologies, which are
• To generate the mesh, in the terminal window type: used to run some simple cases and are the starting point for snappyHexMesh.

1. $> foamCleanTutorials • But have in mind that you can do more elaborated meshes, however, it requires careful setup of
the input dictionary.
2. $> blockMesh
• Have in mind that it can be really tricky to generate multi-block meshes with curve edges.
3. $> checkMesh
• With the training material, you will find a set of supplement slides where we explain how to
4. $> paraFoam create multi-block meshes, add stretching, and how to define curve edges.

• If you want to visualize the blocking topology, type in the terminal

1. $> paraFoam -block

• You can run the rest of the cases following the same steps. Single-block mesh with multi-stretching Multi-block mesh with curved edges and Multi-block mesh with face merging
multi-stretching

349 350
Roadmap Mesh generation using snappyHexMesh

snappyHexMesh
1. Meshing preliminaries • “Automatic split hex mesher. Refines and snaps to surface.”
• For complex geometries, the mesh generation utility snappyHexMesh can be used.
2. What is a good mesh? • The snappyHexMesh utility generates 3D meshes containing hexahedra and split-
3. Mesh quality assessment in OpenFOAM® hexahedra from a triangulated surface geometry in Stereolithography (STL) format.
• The mesh is generated from a dictionary file named snappyHexMeshDict located in
4. Mesh generation using blockMesh. the system directory and a triangulated surface geometry file located in the directory
constant/triSurface.
5. Mesh generation using snappyHexMesh.
6. snappyHexMesh guided tutorials.
7. Mesh conversion
8. Geometry and mesh manipulation utilities

351 352

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


snappyHexMesh workflow snappyHexMesh workflow – Background mesh
• To generate a mesh with snappyHexMesh we proceed as follows: • The background or base mesh can be generated using blockMesh or an
external mesher.
• Generation of a background or base mesh.
• Geometry definition.
• The following criteria must be observed when creating the background
mesh:
• Generation of a castellated mesh or cartesian mesh.
• The mesh must consist purely of hexes.
• Generation of a snapped mesh or body fitted mesh.
• The cell aspect ratio should be approximately 1, at least near the
• Addition of layers close to the surfaces or boundary layer meshing.
STL surface.
• Check/enforce mesh quality.
• There must be at least one intersection of a cell edge with the
blockMesh or external mesher STL surface.
blockMesh or external mesher

Background mesh Geometry (STL file)

Background mesh Geometry (STL file)

snappyHexMesh
snappyHexMesh

OpenFOAM mesh OpenFOAM mesh

353 354
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow – Geometry (STL file) snappyHexMesh workflow
• The STL geometry can be obtained from any geometry modeling tool. • The meshing utility snappyHexMesh reads the dictionary
• The STL file can be made up of a single surface describing the geometry, or snappyHexMeshDict located in the directory system.
multiple surfaces that describe the geometry. • The castellation, snapping, and boundary layer meshing steps are controlled
• In the case of a STL file with multiple surfaces, we can use local refinement by the dictionary snappyHexMeshDict.
in each individual surface. This gives us more control when generating the • The final mesh is always located in the directory
mesh. constant/polyMesh
• The STL geometry is always located in the directory
constant/triSurface

blockMesh or external mesher blockMesh or external mesher

Background mesh Geometry (STL file) Background mesh Geometry (STL file)

snappyHexMesh snappyHexMesh

OpenFOAM mesh OpenFOAM mesh

355 356

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


snappyHexMesh workflow 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: • The process of generating a mesh using snappyHexMesh will be described using this figure.
• In 2D each quad is subdivided in 4
quads. • The objective is to mesh a rectangular shaped region (shaded grey in the figure) surrounding an object
• In 3D each hex is subdivided in 8 described by a STL surface (shaded green in the figure).
hexes. • This is an external mesh (e.g. for external aerodynamics). You can also generate an internal mesh (e.g. flow in
a pipe).
357 358
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow snappyHexMesh workflow

Step 1. Creating the background hexahedral mesh Step 2. Cell splitting at feature edges
• Before snappyHexMesh is executed the user must create a background mesh of hexahedral cells that fills the entire region as • Cell splitting is performed according to the specification supplied by the user in the castellatedMeshControls sub-dictionary in
shown in the figure. This can be done by using blockMesh or any other mesher. the snappyHexMeshDict dictionary.
• The following criteria must be observed when creating the background mesh: • The splitting process begins with cells being selected according to specified edge features as illustrated in the figure.
• The mesh must consist purely of hexes. • The feature edges can be extracted from the STL geometry file using the utility surfaceFeatureExtract.
• 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.
359 360

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


snappyHexMesh workflow snappyHexMesh workflow

Additional internal cells Additional internal cells


splitting splitting

Step 3. Cell splitting at surfaces Step 4. Cell removal


• Following feature edges refinement, cells are selected for splitting in the locality of specified surfaces as illustrated in the figure. • Once the feature edges and surface splitting is complete, a process of cell removal begins.
• The surface refinement (splitting) is performed according to the specification supplied by the user in the • The region in which cells are retained are simply identified by a location point within the region, specified by the locationInMesh
refinementMeshControls in the castellatedMeshControls sub-dictionary in the snappyHexMeshDict dictionary. keyword in the castellatedMeshControls sub-dictionary in the snappyHexMeshDict dictionary.
• Notice that we added additional internal cells splitting. This new cell region can be used to define a source term or it can be put • Cells are retained if, approximately speaking, 50% or more of their volume lies within the region.
into motion.

361 362
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow snappyHexMesh workflow

Additional internal cells Additional internal cells


splitting splitting

Step 5. Cell splitting in specified regions Step 6. Snapping to surfaces


• Those cells that lie within one or more specified volume regions can be further split by a region (in the figure, the rectangular • After deleting the cells in the region specified and refining the volume mesh, the points are snapped on the surface to create a
region within the red rectangle). conforming mesh.
• The information related to the refinement of the volume regions is supplied by the user in the refinementRegions block in the • The snapping is controlled by the user supplied information in the snapControls sub-dictionary in snappyHexMeshDict.
castellatedMeshControls sub-dictionary in the snappyHexMeshDict dictionary. • Sometimes, the default snapControls options are not enough and you will need to adjust the values to get a good mesh, so it is
• This is a valid castellated or cartesian mesh that can be used for a simulation. advisable to save the intermediate steps with a high writing precision (controlDict).
• This is a valid snapped or body fitted mesh that can be used for a simulation.
363 364

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


snappyHexMesh workflow snappyHexMesh in action
www.wolfdynamics.com/wiki/shm/ani.gif

Additional internal cells


splitting

Step 7. Mesh layers


• The mesh output from the snapping stage may be suitable for simulation, although it can produce some irregular cells along
boundary surfaces.
• There is an optional stage of the meshing process which introduces boundary layer meshing in selected parts of the mesh.
• This information is supplied by the user in the addLayersControls sub-dictionary in the snappyHexMeshDict dictionary.
• This is the final step of the mesh generation process using snappyHexMesh.
• This is a valid body fitted mesh with boundary layer meshing, that can be used for a simulation.
365 366
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary.

castellatedMesh true; //or false

• Let us study the snappyHexMesh dictionary in snap true;


addLayers true;
//or false
//or false

details. geometry
{
Definition of geometry entities
to be used for meshing

• We are going to work with the case we just saw in }


...
...

action. castellatedMeshControls
Definition of feature, surface
and volume mesh refinement

• You will find this case in the directory:


{
...
...
}
Definition of surface mesh
snapControls snapping and advanced
{ parameters
... • Open the dictionary snappyHexMeshDict with your favorite text
... editor (we will use gedit).
}

$PTOFC/101SHM/M101_WD addLayersControls
{
Definition of boundary layer
meshing and advanced
parameters
• The snappyHexMesh dictionary is made up of five sections, namely:
geometry, castellatedMeshControls, snapControls,
addLayersControls and meshQualityControls. Each section
... controls a step of the meshing process.
...
} • In the first three lines we can turn off and turn on the different
Definition of mesh quality meshing steps. For example, if we want to generate a body fitted
meshQualityControls mesh with no boundary layer we should proceed as follows:
{ metrics
... castellatedMesh true;
... snap true;
367 } addLayers false; 368

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
Geometry controls section
castellatedMesh true; //or false • Have in mind that there are more than 70 geometry
snap true; //or false {
addLayers true; //or false parameters to control in
snappyHexMeshDict dictionary. wolfExtruded.stl
{
STL file to read

geometry type triSurfaceMesh;


{ name wolf;
... • Adding the fact that there is no native GUI, it Name of the surface inside snappyHexMesh

... can be quite tricky to control the mesh regions Use this option if you have a STL with multiple patches defined
} {
generation process. wolflocal This is the name of the region or surface patch in the STL
castellatedMeshControls {
{ name wolf_wall; User-defined patch name. This is the final name of the patch
... • Nevertheless, snappyHexMesh generates }
... }
} really good hexa dominant meshes. }
• In this section we read in the STL geometry. Remember, the input
snapControls box Name of geometrical entity
geometry is always located in the directory constant/triSurface
{ • Hereafter, we will only comment on the most {
... type searchableBox;
...
important parameters. min (-100.0 -120.0 -50.0 );
• We can also define geometrical entities that can be used to refine the
mesh, create regions, or generate baffles.
} max (100.0 120.0 150.0 );
}
addLayersControls • The parameters that you will find in the • You can add multiple STL files.

{ snappyHexMeshDict dictionaries distributed sphere Name of geometrical entity • If you do not give a name to the surface, it will take the name of the
... { STL file.
... with the tutorials, in our opinion are robust and type searchableSphere; Note 1
} centre (120.0 -100.0 50.0 ); •
will work most of the times. radius 40.0;
The geometrical entities are created inside snappyHexMesh.

meshQualityControls } Note 1:
{ If you want to know what geometrical entities are available, just
... } misspelled something in the type keyword.
... May be located In a separated file
} 369 370
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
Castellated mesh controls section Castellated mesh controls section
castellatedMeshControls castellatedMeshControls
{ {
//Refinement parameters
maxLocalCells 100000; // Refinement parameters
maxGlobalCells 2000000; Note 1 maxLocalCells 100000;
nCellsBetweenLevels 3; maxGlobalCells 2000000;
... minRefinementCells 0;
... maxLoadUnbalance 0.10;
nCellsBetweenLevels 3; Note 1
//Explicit feature edge refinement
features Dictionary block //Local curvature and
( //feature angle refinement
... resolveFeatureAngle 30; Note 2
...
); planarAngle 30;

//Surface based refinement allowFreeStandingZoneFaces true;


refinementSurfaces Dictionary block
{
... //Explicit feature edge refinement
• In the castellatedMeshControls section, we define the global Note 1:
... features Dictionary block
refinement parameters, explicit feature edge refinement, This parameter controls the transition between cell
} (
surface based refinement, region-wise refinement and the refinement levels.
{
material point.
//Region-wise refinement file "wolfExtruded.eMesh"; Note 3
Note 2:
refinementRegions Dictionary block level 2;
• In this step, we are generating the castellated mesh. This parameter controls the local curvature refinement. The
{ }
higher the value, the less features it captures. For example,
... );
Note 1: if you use a value of 100 it will not add refinement in high
...
Maximum number of cells in the domain. If the mesher reach this curvature areas. It also controls edge feature snapping, high
} ...
number it will not add more cells. values will not resolve sharp angles in surface intersections.
...
//Mesh selection ...
Note 3:
locationInMesh (-100.0 0.0 50.0 ); Note 2 Note 2: This file is automatically created when you use the utility
} }
The material point indicates where we want to create the mesh, surfaceFeatureExtract. The file is located in the
that is, inside or outside the body to be meshed. 371 directory constant/triSurface 372

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
Castellated mesh controls section Castellated mesh controls section
castellatedMeshControls castellatedMeshControls
{ {

... //Surface based refinement


... refinementSurfaces Dictionary block
... {

//Surface based refinement ...


refinementSurfaces Dictionary block ...
{ ...
//This surface or geometrical entity
//wolf was defined in the geometry section //was defined in geometry section
wolf Note 1 sphere Note 1
{ {
level (1 1);
level (1 1); //Global refinement Name of faceZone
faceZone face_inner;
regions Note 2 cellZone cell_inner; Name of cellZone
{
cellZoneInside inside; Create inner cellZone
wolflocal Note 3
Note 1:
{ //faceType internal; Create internal faces from faceZone
The surface wolf was defined in the geometry section.
level (2 4); Local refinement Uncomment to create the internal faceZone
}
Note 2:
patchInfo Note 1:
The region wolflocal was defined in the geometry section.
{ } Optional specification of what to do with faceZone faces:
type wall; Note 4
Note 3:
} ... internal: keep them as internal faces (default)
Named region in the STL file. This refinement is local.
} ... baffle: create baffles from them. This gives more freedom in mesh
To use the surface refinement in the regions, the local
} } motion
regions must exist in STL file. We created a pointer to this
} boundary: create free-standing boundary faces (baffles but
region in the geometry section.
... without the shared points)
...
Note 4:
} 373 e.g., faceType internal; 374
You can only define patches of type wall or patch.
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
Castellated mesh controls section Castellated mesh controls section
castellatedMeshControls castellatedMeshControls
{ {

... ...
... ...
... ...

//Region-wise refinement //Region-wise refinement


refinementRegions Dictionary block refinementRegions Dictionary block
{ {

//This region or geometrical entity //This region or geometrical entity


//was defined in the geometry section //was defined in the geometry section

box Note 1 box


{ {
mode inside; mode inside;
levels (( 1 1 )); levels (( 1 1 ));
} }

} }
This point defines where do you want the mesh.
Can be internal mesh or external mesh.
//Mesh selection Note 1: //Mesh selection
locationInMesh (-100.0 0.0 50.0 ); This region or geometrical entity was created in the geometry section. 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.

At this point we have a valid mesh (cartesian)


375 376

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
Snap mesh controls section Boundary layer mesh controls section
snapControls addLayersControls
{ {
//Global parameters
//Number of patch smoothing iterations relativeSizes true;
//before finding correspondence to surface expansionRatio 1.2;
nSmoothPatch 3; finalLayerThickness 0.5;
minThickness 0.01;
tolerance 2.0;
layers Note 1
//- Number of mesh displacement relaxation {
//iterations. wolf_wall Note 2
nSolveIter 100; Note 1 {
nSurfaceLayers 3;
//- Maximum number of snapping relaxation //Local parameters
//iterations. Should stop before upon //expansionRatio 1.3;
//reaching a correct mesh. //finalLayerThickness 0.3;
nRelaxIter 10; Note 2 //minThickness 0.1;
}
// Feature snapping }
// Advanced settings
//Number of feature edge snapping iterations. nGrow 0;
nFeatureSnapIter 10; Note 3 Note 1: featureAngle 130; Note 3 Note 1:
The higher the value the better the body fitted mesh. The default value maxFaceThicknessRatio 0.5; In this section we select the patches where we want to add the
//Detect (geometric only) features by is 30. If you are having problems with the mesh quality (related to the nSmoothSurfaceNormals 1; layers. We can add multiple patches (if they exist).
//sampling the surface (default=false). snapping step), try to increase this value to 300. Have in mind that this nSmoothThickness 10;
implicitFeatureSnap false; will increase the meshing time. minMedianAxisAngle 90; Note 2:
maxThicknessToMedialRatio 0.3; This patch was created in the geometry section.
// Use castellatedMeshControls::features Note 2: nSmoothNormals 3;
// (default = true) Increase this value to improve the quality of the body fitted mesh. slipFeatureAngle 30; Note 3:
explicitFeatureSnap true; nRelaxIter 5; Specification of feature angle above which layers are collapsed
Note 3: nBufferCellsNoExtrude 0; automatically.
multiRegionFeatureSnap false; Increase this value to improve the quality of the edge features. nLayerIter 50;
nRelaxedIter 20; • In this step, we are generating the boundary layer mesh.
} • In this step, we are generating the body fitted mesh. }
377 378
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
Mesh quality controls section Mesh debug and write controls sections
meshQualityControls debugFlags
{ (
maxNonOrtho 75; Note 1 // write intermediate meshes
mesh
maxBoundarySkewness 20;
// write current mesh intersections as .obj files
maxInternalSkewness 4; Note 2 intersections

maxConcave 80; // write information about explicit feature edge


// refinement
minVol 1E-13; featureSeeds

//minTetQuality 1e-15; // write attraction as .obj files


minTetQuality -1e+30; attraction

minArea -1; // write information about layers


layerInfo
minTwist 0.02; );

minDeterminant 0.001;
Note 1:
writeFlags
Maximum non-orthogonality angle.
minFaceWeight 0.05; (
// write volScalarField with cellLevel for • At the end of the dictionary you will find the sections: debugFlags
Note 2:
minVolRatio 0.01; // postprocessing and writeFlags
Maximum skewness angle.
scalarLevels
minTriangleTwist -1; • By default they are commented. If you uncomment them you will
• During the mesh generation process, the mesh quality is continuously
// write cellSets, faceSets of faces in layer enable debug information.
monitored.
minFlatness 0.5; • The mesher snappyHexMesh will try to generate a mesh using the layerSets
• debugFlags and writeFlags will produce a lot of outputs that you
mesh quality parameters defined by the user.
nSmoothScale 4; // write volScalarField for layer coverage can use to post process and troubleshoot the different steps of
• If a mesh motion or topology change introduces a poor quality cell or
layerFields the meshing process.
face the motion or topology change is undone to revert the mesh back
errorReduction 0.75; );
to a previously valid error free state.
}
379 380

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


Let us generate the mesh of the wolf dynamics logo. Let us generate the mesh of the wolf dynamics logo.
• This tutorial is located in the directory:
• $PTOFC/101SHM/M101_WD • To generate the mesh, in the terminal window type:

• In this case we are going to generate a body fitted mesh with boundary layer. This is an
1. $> foamCleanTutorials
external mesh. 2. $> blockMesh
• Before generating the mesh take a look at the dictionaries and files that will be used. $> surfaceFeatureExtract
3.
• These are the dictionaries and files that will be used.
4. $> snappyHexMesh
• system/snappyHexMeshDict
5. $> checkMesh –latestTime
• system/surfaceFeatureExtractDict
• system/meshQualityDict
• system/blockMeshDict • To visualize the mesh, in the terminal window type:
• constant/triSurface/wolfExtruded.stl • $> paraFoam
• constant/triSurface/wolfExtruded.eMesh

• Remember to use the VCR controls in paraView/paraFoam to visualize the


• The file wolfExtruded.eMesh is generated after using the utility mesh intermediate steps.
surfaceFeatureExtract, which reads the dictionary surfaceFeatureExtractDict.
381 382
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us generate the mesh of the wolf dynamics logo. Let us generate the mesh of the wolf dynamics logo.

• In the case directory you will find the time folders 1, 2, and 3, which contain • If you want to avoid the additional steps of transferring the final mesh to the
the castellated mesh, snapped mesh and boundary layer mesh respectively. directory constant/polyMesh by not saving the intermediate steps, you
In this case, snappyHexMesh automatically saved the intermediate steps. can proceed as follows:
• Before running the simulation, remember to transfer the solution from the
latest mesh to the directory constant/polyMesh, in the terminal type: • $> snappyHexMesh –overwrite

1. $> cp 3/polyMesh/* constant/polyMesh • When you proceed in this way, snappyHexMesh automatically saves the
2. $> rm –rf 1 final mesh in the directory constant/polyMesh.
3. $> rm –rf 2 • Have in mind that you will not be able to visualize the intermediate steps.
4. $> rm –rf 3 • Also, you will not be able to restart the meshing process from a saved state
$> checkMesh –latestTime (castellated or snapped mesh).
5.
• Unless it is strictly necessary, from this point on we will not save the
intermediate steps.
383 384

Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh


The constant/polyMesh/boundary file The constant/polyMesh/boundary file
• At this point, we have a valid mesh to run a simulation. Number of surface patches
• Have in mind that before running the simulation you will need to set the boundary and initial 18
19
9
(
In the list bellow there must be 9 patches
conditions in the directory 0. 20 minX definition.
21 {
22 type wall;
• Let us talk about the constant/polyMesh/boundary file, 23 inGroups 1(wall);
24 nFaces 400;
• First of all, this file is automatically generated after you create the mesh or you convert it 25
26 }
startFace 466399;
maxY
wolf_wall

from a third-party format. 27


28
maxX
{
29 type wall;
• In this file, the geometrical information related to the base type patch of each boundary of 30 inGroups 1(wall);
31 nFaces 400;
the domain is specified. 32 startFace 466799;
33 } minZ
• The base type boundary condition is the actual surface patch where we are going to apply 34
35
minY
{
a numerical type boundary condition. 36
37
type
inGroups
empty;
1(wall);

• The numerical type boundary condition assign a field value to the surface patch (base 38
39
nFaces
startFace
400;
467199;
40 }
type). 41 maxY
minX maxX
42 {
• You define the numerical type patch (or the value of the boundary condition), in the 43 type wall;
44 inGroups 1(wall);
directory 0 or time directories. 45 nFaces 400;
46 startFace 467599;
• The name and base type of the patches was defined in the dictionaries blockMeshDict 47
48
}
minZ maxZ
and snappyHexMeshDict. 49
50
{
type wall;
51 inGroups 1(wall);
• You can change the name if you do not like it. Do not use strange symbols or white 52 nFaces 400;
53 startFace 467999;
spaces. 54 }
sphere
• You can also change the base type. For instance, you can change the type of the patch minY
sphere_slave
maxY from wall to patch. 385 386
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
The constant/polyMesh/boundary file The constant/polyMesh/boundary file

18 9 Name 55 maxZ
19 ( Name and type of the surface patches 56 { Name and type of the surface patches
20 minX 57 type wall;
21 { • The name and base type of the patch is given by the user. 58 inGroups 1(wall); • The name and base type of the patch is given by the user.
22 type wall; Type 59 nFaces 400;
23 inGroups 1(wall); 60 startFace 466399;
24 nFaces 400; • In this case the name and base type was assigned in the 61 } Name • In this case the name and base type was assigned in the
25
26 }
startFace 466399;
dictionaries blockMeshDict and snappyHexMeshDict. 62
63
wolf_wall
{
dictionaries blockMeshDict and snappyHexMeshDict.
27 maxX 64 type wall; Type
28 {
nFaces • You can change the name if you do not like it. Do not use 65 inGroups 1(wall); • You can change the name if you do not like it. Do not use
29 type wall; 66 nFaces 400;
30 inGroups 1(wall); startFace strange symbols or white spaces. 67 startFace 466799; strange symbols or white spaces.
31 nFaces 400; 68 }
32
33 }
startFace 466799;
• You can also change the base type. For instance, you can 69
70
sphere
{ nFaces • You can also change the base type. For instance, you can
34 minY change the type of the patch maxY from wall to patch. 71 type empty; startFace change the type of the patch maxY from wall to patch.
35 { 72 inGroups 1(wall);
36 type empty; 73 nFaces 400;
37 inGroups 1(wall); 74 startFace 467199;
38 nFaces 400; 75 }
39 startFace 467199; nFaces and startFace keywords 76 sphere_slave nFaces and startFace keywords
40 } 77 {
41 maxY • Unless you know what you are doing, you do not 78 type wall; • Unless you know what you are doing, you do not
42 { 79 inGroups 1(wall);
43 type wall; need to change this information. 80 nFaces 400; need to change this information.
44 inGroups 1(wall); 81 startFace 467599;
45
46
nFaces
startFace
400;
467599;
• Basically, this is telling you the starting face and ending face 82
83 )
}
• Basically, this is telling you the starting face and ending face
47 } of the patch. of the patch.
48 minZ
49 {
50 type wall; • This information is created automatically when generating • This information is created automatically when generating
51 inGroups 1(wall);
52 nFaces 400;
the mesh or converting the mesh. the mesh or converting the mesh.
53 startFace 467999;
54 }

387 388

Mesh generation using snappyHexMesh Roadmap


Cleaning the case directory
• When generating the mesh using OpenFOAM®, it is extremely important to 1. Meshing preliminaries
start from a clean case directory.
2. What is a good mesh?
• To clean all the case directory, in the terminal type:
3. Mesh quality assessment in OpenFOAM®
• $> foamCleanTutorials
4. Mesh generation using blockMesh.
• To only erase the mesh information, in the terminal type:
5. Mesh generation using snappyHexMesh.
• $> foamCleanPolyMesh
6. snappyHexMesh guided tutorials.
• If you are planning to start the meshing from a previous saved state, you do
not need to clean the case directory.
7. Mesh conversion
8. Geometry and mesh manipulation utilities
• Before proceeding to compute the solution, remember to always check the
quality of the mesh.

389 390
snappyHexMesh guided tutorials 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 • Meshing with snappyHexMesh – Case 1.
and introduce a few advanced features. • 3D cylinder with feature edge refinement (external mesh).
• This case is located in the directory $PTOFC/101SHM/M1cyl • You will find this case in the directory:

$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.
391 392

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement. 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
{

...
...
...

//Local curvature and


//feature angle refinement
Sphere with no edge refinement Cylinder with edge refinement Cylinder with no edge refinement resolveFeatureAngle 30; To control curvature refinement

...
...
...

• If the geometry has sharp angles and you want to resolve those edges, you should use edge //Explicit feature edge refinement
features
refinement. (
{
• In the left figure there is no need to use edge refinement as there are no sharp angles. file “surfacemesh.eMesh";
To enable and
control edge
level 0;
refinement level
• 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. ...
...

393 } 394
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.

How resolveFeatureAngle works? How resolveFeatureAngle works?

angle < resolveFeatureAngle angle > resolveFeatureAngle


If angle is more than resolveFeatureAngle
No curvature refinement If angle is more than resolveFeatureAngle
Curvature refinement
the adjacent STL faces will be marked for the adjacent STL faces will be marked for
refinement refinement
angle angle

resolveFeatureAngle resolveFeatureAngle
STL STL

0: mark the whole surface for refinement 0: mark the whole surface for refinement
180: do not mark any STL face for refinement 180: do not mark any STL face for refinement

395 396

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• How do we control surface refinement? • How do we create refinement regions?
• In the file snappyHexMeshDict, look for the following entry: • In the file snappyHexMeshDict, look for the following entry:

castellatedMeshControls geometry
{
{
...
... ...
... ...
...
//Surface based refinement
refinementSurfaces refinementBox Name of refinement region
{
To control surface refinement.
{
banana_stlSurface
{ The first digit controls the global type searchableBox; Geometrical entity type.
surface refinement level and the second min ( -2 -2 -2);
level (2 4); digit controls the curvature refinement
This is the zone where we
} level, according to the angle set in the max ( 2 2 2); want to apply the refinement
} entry resolveFeatureAngle }
...
...
... Dimensions of geometrical entity
... ...
...
} };

397 398
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• How do we create refinement regions?
• In the file snappyHexMeshDict, look for the following entry: Effect of various parameters on edge capturing and surface refinement

castellatedMeshControls
{
...
...
...

refinementRegions
{ Name of the region
refinementBox created in the geometry section
{
mode inside; Type of refinement (inside,
Explicit feature edge refinement level 0 Explicit feature edge refinement level 0
levels ((1e15 1)); outside, or distance mode)
resolveFeatureAngle 110 resolveFeatureAngle 60
}
Surface based refinement level (2 2) Surface based refinement level (2 2)
}
Refinement level
... • To control edges capturing you can decrease the value of resolveFeatureAngle.
... Distance from the surface • Be careful, this parameter also controls curvature refinement, so if you choose a low
... A large value covers the whole region
} value you also will be adding a lot of refinement on the surface.
399 400

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement. 3D Cylinder with edge refinement.

Effect of various parameters on edge capturing and surface refinement Effect of various parameters on edge capturing and surface refinement

Explicit feature edge refinement level 0 Explicit feature edge refinement level 4 Explicit feature edge refinement level 6 Explicit feature edge refinement level 0
resolveFeatureAngle 60 resolveFeatureAngle 60 resolveFeatureAngle 5 resolveFeatureAngle 5
Surface based refinement level (2 2) Surface based refinement level (2 2) 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 • To control edges refinement level, you can change the value of the explicit feature
edge refinement level. edge refinement level.

401 402
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.

Effect of various parameters on edge capturing and surface refinement Effect of various parameters on edge capturing and surface refinement

Explicit feature edge refinement level 0 Explicit feature edge refinement level 4 Explicit feature edge refinement level 0 Explicit feature edge refinement level 0
resolveFeatureAngle 60 resolveFeatureAngle 60 resolveFeatureAngle 60 resolveFeatureAngle 5
Surface based refinement level (2 4) Surface based refinement level (2 2) Surface based refinement level (2 4) Surface based refinement level (2 4)

• To control surface refinement level, you can change the value of the surface based • To control surface refinement due to curvature together with control based surface
refinement level. refinement level, you can change the value of resolveFeatureAngle, and surface
• The first digit controls the global surface refinement level and the second digit based refinement level
controls the curvature refinement level. 403 404

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• Let us explore the dictionary surfaceFeatureExtractDict used by the • Let us explore the dictionary surfaceFeatureExtractDict used by the
utility surfaceFeatureExtract. utility surfaceFeatureExtract.
• This utility will extract surface features (sharp angles) according to an angle • This utility will extract surface features (sharp angles) according to an angle
criterion (includedAngle). criterion (includedAngle).

Name of the STL. Features edges Name of the STL. If angle is less than includedAngle
surfacemesh.stl The STL file is located surfacemesh.stl The STL file is located this feature will be marked
{ in constant/triSurface { in constant/triSurface

extractionMethod extractFromSurface; extractionMethod extractFromSurface;


angle
extractFromSurfaceCoeffs extractFromSurfaceCoeffs
{ {
Angle criterion Angle criterion
includedAngle 150; includedAngle 150;
to extract features to extract features
} } STL
subsetFeatures subsetFeatures includedAngle
{ {
nonManifoldEdges yes; nonManifoldEdges yes;
openEdges yes; openEdges yes;
} } Mark edges whose adjacent surface normals
are at an angle less than includedAngle
writeObj yes; If you want to save writeObj yes; If you want to save
the .obj files Features edges the .obj files 0: selects no edges
} } 180: selects all edge

405 406
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• If you want to have a visual representation of the feature edges, you can use • In this case we are going to generate a body fitted mesh with edge refinement. This is an
paraview/paraFoam. external mesh.
• Just look for the filter Feature Edges. • These are the dictionaries and files that will be used.
• Have in mind that the angle you need to define in paraview/paraFoam is the complement of the • system/snappyHexMeshDict
angle you define in the dictionary surfaceFeatureExtractDict
• system/surfaceFeatureExtractDict
• system/meshQualityDict
• system/blockMeshDict
• constant/triSurface/surfacemesh.stl
• constant/triSurface/surfacemesh.eMesh

• The file surfacemesh.eMesh is generated after using the utility surfaceFeatureExtract,


which reads the dictionary surfaceFeatureExtractDict.
• The utility surfaceFeatureExtract, 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.

407 408

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement.
• Meshing with snappyHexMesh – Case 2.
• Let us generate the mesh, in the terminal window type: • 3D cylinder with feature edge refinement and boundary layer (external
mesh).
1. $> foamCleanTutorials
• You will find this case in the directory:
2. $> surfaceFeatureExtract
3. $> blockMesh
$PTOFC/101SHM/M1_cyl/C2
4. $> snappyHexMesh –overwrite
5. $> checkMesh –latestTime
6. $> paraFoam
• 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.
• In step 2 we extract the sharp angles from the geometry.
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
• In step 3 we generate the background mesh. 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.
• In step 4 we generate the body fitted mesh. Have in mind that as we use the • We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
option –overwrite, we are not saving the intermediate steps. way, you will get used with the command line interface and OpenFOAM® commands.

• In step 5 we check the mesh quality. • If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
409 410
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.
• How do we enable boundary layer?
• In the file snappyHexMeshDict, look for the following entry:

castellatedMesh true; //or false


Set this parameter to snap true; //or false
true if you want to
enable boundary layer
addLayers true; //or false
meshing

...
...
...
Your final mesh should looks like this one

411 412

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.
• How do we enable boundary layer? • How do we control boundary layer collapsing?
• In the file snappyHexMeshDict, look for the section addLayersControls: • In the file snappyHexMeshDict, look for the section addLayersControls:

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 // Advanced settings
{ boundary layer mesh. nGrow 0;
nSurfaceLayers 3; Increase this value to avoid BL
}
featureAngle 130; collapsing
}
...
// Advanced settings
...
... ...
...
...
}
}

413 414
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.

Effect of different parameters on the boundary layer meshing Effect of different parameters on the boundary layer meshing

relativeSizes true relativeSizes false


expansionRatio 1.2 expansionRatio 1.2
finalLayerThickness 0.5 firstLayerThickness 0.025
minThickness 0.1 minThickness 0.01
featureAngle 130 featureAngle 130 • When the option relativeSizes is true, the boundary layer meshing is done relative to the size
nSurfaceLayers 3 nSurfaceLayers 3 of the cells next to the surface.
Surface based refinement level (2 4) Surface based refinement level (2 4)
• 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.
415 416

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.

Effect of different parameters on the boundary layer meshing Effect of different parameters on the boundary layer meshing

relativeSizes true relativeSizes true


expansionRatio 1.2 expansionRatio 1.2
finalLayerThickness 0.5 finalLayerThickness 0.5
minThickness 0.1 minThickness 0.1
featureAngle 130 featureAngle 130
nSurfaceLayers 3 nSurfaceLayers 3
Surface based refinement level (2 4) Surface based refinement level (2 2)

• When the option relativeSizes is false, we give the actual thickness of the layers. • When the option relativeSizes is true and in order to have a uniform boundary layer, we need
• This option requires a lot user intervention but it guarantees a uniform boundary layer and the to have a uniform surface refinement.
desired layer thickness. 417 • Nevertheless, we still do not have control on the desired thickness of the first layer. 418
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.

Effect of different parameters on the boundary layer meshing Effect of different parameters on the boundary layer meshing

relativeSizes true relativeSizes true relativeSizes false relativeSizes false


expansionRatio 1.2 expansionRatio 1.2 nSurfaceLayers 6 nSurfaceLayers 6
finalLayerThickness 0.5 finalLayerThickness 0.5 Refinement region at the stl surface:
minThickness 0.1 minThickness 0.1 mode distance;
featureAngle 130 featureAngle 30 levels ((0.05 4))
nSurfaceLayers 3 nSurfaceLayers 3
Surface based refinement level (2 2) Surface based refinement level (2 2)
• The disadvantage of setting relativeSizes to false, is that it is difficult to control the expansion
• To avoid boundary layer collapsing close to the corners, we can increase the value of the ratio from the boundary layer meshing to the far mesh.
boundary layer parameter featureAngle. • To control this transition, we can add a refinement region at the surface with distance mode.
419 420

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.

• To generate the mesh, in the terminal window type: • At the end of the meshing process you will get the following information
regarding the boundary layer meshing:
1. $> foamCleanTutorials
2. $> surfaceFeatureExtract
patch faces layers overall thickness
3. $> blockMesh
[m] [%]
4. $> snappyHexMesh -overwrite
----- ----- ------ --- ---
5. $> checkMesh –latestTime banana_stlSurface 4696 3 0.0569 95.9
6. $> paraFoam
Layer mesh : cells:48577 faces:157942 points:61552

• This is a general summary of the boundary layer meshing.


• Pay particular attention to the overall and thickness information.
• Overall is roughly speaking the thickness of the whole boundary layer.
• Thickness is the percentage of the patch that has been covered with the boundary layer mesh. A thickness of
421 100% means that the whole patch has been covered (a perfect BL mesh). 422
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.

• Then you can use paraview/paraFoam to visualize the boundary layer


• If you want to visualize the boundary layer thickness, you can enable coverage.
writeFlags in the snappyhexMeshDict dictionary,

...
...
...

writeFlags
(
Boundary layer thickness and number of layers
scalarLevels; // write volScalarField with cellLevel for postprocessing
layerSets; // write cellSets, faceSets of faces in layer
layerFields; // write volScalarField for layer coverage
);

...
...
...

The yellow surface represent the BL coverage


423 424

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer. 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 • Remember, before restarting the meshing you will need to modify the
try different layer parameters, you do not need to start the meshing process snappyHexMeshDict dictionary as follows:
from scratch.
• To restart the meshing process from a saved state you need to save the castellatedMesh false;
intermediate steps (castellation and snapping), and then create the inflation snap false;
layers starting from the snapped mesh.
addLayers true;
• That is, do not use the option snappyHeshMesh -overwrite.
• Also, in the dictionary controlDict remember to set the entry startFrom • At this point, you can restart the meshing process by typing in the terminal,
to latestTime or the time directory where the snapped mesh is saved (in
• $> snappyHexMesh
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 • By the way, you can restart the boundary layer mesh from a previous mesh
snappyHexMeshDict dictionary. 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.
425 426
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
• Meshing with snappyHexMesh – Case 3.
with multiple surfaces.
• 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

STL visualization with a single surface using paraview (the STL visualization with multiple surfaces using paraview (each
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of single surface in represented with a single color) color corresponds to a different surface)

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 • When you use a STL with multiple surfaces, you have more control over the meshing process.
automatically by typing in the terminal, for example, sh run_solver. • By default, STL files are made up of one single surface.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this • If you want to create the multiple surfaces you will need to do it in the solid modeler.
way, you will get used with the command line interface and OpenFOAM® commands. • Alternatively, you can split the STL manually or using the utility surfaceAutoPatch.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases. • Loading multiple STLs is equivalent to using a STL with multiple surfaces.
427 428

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer, using a STL file 3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces. 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 boundary layer meshing
patch1
{
name surface1;
}
patch2
{
name surface2;
}
}
• 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. 429 } 430
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file 3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces. with multiple surfaces.
• How do we refine user defined surface patches? • How do we control curvature refinement on surface patches?
• In the file snappyHexMeshDict, look for the following entry: • In the file snappyHexMeshDict, look for the following entry:
castellatedMeshControls castellatedMeshControls
{ {
... ...
... ...
... ...
refinementSurfaces refinementSurfaces
{ {
level (2 2); Global refinement level level (2 2); Global refinement level
regions regions
{ {
patch0 Local surface patch patch0 Local surface patch
{ {
level (2 2); Local refinement level level (2 4); Local curvature refinement (in red)
patchInfo patchInfo
{ {
type wall; Type of the patch. type wall;
} This information is optional }
} }
... ...
... ...
... ...
} }
} }
... ...
... ...
... ...
} }
431 432

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer, using a STL file 3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces. with multiple surfaces.
• How do we control curvature refinement on surface patches? • How do we control boundary layer meshing on the surface patches?
• In the file snappyHexMeshDict, look for the following entry: • In the file snappyHexMeshDict, look for the following entry:
addLayersControls
{

castellatedMeshControls //Global parameters


relativeSizes true;
{ expansionRatio 1.2;
Global BL parameters
finalLayerThickness 0.5;
... minThickness 0.1;
layers
... {
... “surface.*” POSIX wildcards are permitted
{
nSurfaceLayers 5;
//Local curvature and }
//feature angle refinement surface0 Local surface patch
The default value is 30.
{
resolveFeatureAngle 60; Using a higher value will capture
nSurfaceLayers 3;
less features.
expansionRatio 1.0;
finalLayerThickness 0.25; Local BL parameters
... minThickness 0.1;
... }
... }

//Advanced settings
} ...
...
...
433 } 434
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file 3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces. with multiple surfaces.

• Let us first create the STL file with multiple surfaces. • If you open the file output.stl, you will notice that there are three
• In the directory geo, you will find the original STL file. surfaces defined in the STL file. The different surfaces are defined in by the
• In the terminal type: following sections:

1. $> cd geo solid patch0


2. $> surfaceAutoPatch geo.stl output.stl 130 … Surface patch 1 • The name of the solid sections are
automatically given by the utility
$> cp output.stl ../constant/triSurface/surfacemesh.stl endsolid patch0
3. surfaceAutoPatch.
4. $> cd ..
solid patch1
5. $> paraview • The convention is as follows: patch0,
… Surface patch 2
patch1, pathc2, … patchN.
endsolid patch1
• 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 • If you do not like the names, you can
surfaceFeatureExtract). It writes the new STL geometry in the file output.stl. solid patch2
change them directly in the STL file.
• By the way, it is better to create the STL file with multiple surfaces directly in the solid modeler. … Surface patch 3

• FYI, there is an equivalent utility for meshes, autoPatch. So if you forgot to define the endsolid patch2
patches, this utility will automatically find the patches according to an angle criterion. 435 436

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


3D Cylinder with edge refinement and boundary layer, using a STL file 3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces. with multiple surfaces.

• The new STL file is already in the constant/triSurface directory. • This case is ready to run using the solver simpleFoam. But before running,
• To generate the mesh, in the terminal window type: you will need to set the boundary and initial conditions.
• You will need to manually modify the file constant/polyMesh/boundary
1. $> foamCleanTutorials • Remember:
2. $> surfaceFeatureExtract • Base type boundary conditions are defined in the file boundary located
3. $> blockMesh in the directory constant/polyMesh.
4. $> snappyHexMesh -overwrite • Numerical type boundary conditions are defined in the field variables
5. $> checkMesh –latestTime 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
• To visualize the mesh, in the terminal window type: boundary conditions needs to be the same.
6. $> paraFoam • Also, the base type boundary condition needs to be compatible with the
numerical type boundary condition.
437 438
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer, using a STL file
with multiple surfaces. • Meshing with snappyHexMesh – Case 4.
• This case is ready to run with simpleFoam. • 2D cylinder (external mesh)
• If you are in a hurry and you do not want to create/edit the files 0/U, 0/p, • You will find this case in the directory:
constant/polyMesh/boundary, follow these steeps to run the case:

1. $> cp 0_org/* 0 $PTOFC/101SHM/M1_cyl/C4


2. $> cp system/boundary_org constant/polyMesh/boundary
3. $> renumberMesh –overwrite
4. $> simpleFoam > log | tail –f log • 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.
439 440

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


2D Cylinder 2D Cylinder

Geometry width
FACE 1

The utility extrudeMesh works by


projecting FACE 1 into FACE 2.
Therefore, the faces need to be
parallel.

FACE 2 Background mesh width

• At most, the input geometry and the background mesh need to have the same width.
From 3D To 2D • If the input geometry is larger than the background mesh, it will be automatically cut by the faces
of the background mesh.
• To generate a 2D mesh using snappyHexMesh, we need to start from a 3D. After all, • In this case, the input geometry will be cut by the two lateral patches of the background mesh.
snappyHexMesh is a 3D mesher. • If you want to take advantage of symmetry in 3D, you can cut the geometry in half using one of
• To generate a 2D mesh (and after generating the 3D mesh), we use the utility the faces of the background mesh.
extrudeMesh. • When dealing with 2D
• Extracting the features edges is optional for the 2D geometry extremes, but it is recommended if
• The utility extrudeMesh works by projecting a face into a mirror face. Therefore, there are internal edges that you want to resolve.
the faces need to parallel. 441 442
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
2D Cylinder 2D Cylinder
• How do we create the 2D mesh?
• After generating the 3D mesh, we use the utility extrudeMesh. • To generate the mesh, in the terminal window type:
• This utility reads the extrudeMeshDict,
1. $> foamCleanTutorials
constructFrom patch; 2. $> blockMesh
sourceCase “.” 3. $> snappyHexMesh –overwrite
sourcePatches (minZ); Name of source patch
4. $> extrudeMesh
exposedPatchName maxZ; Name of the mirror patch
5. $> checkMesh –latestTime
extrudeModel linearNormal
6. $> paraFoam
Number of layers to use in the linear extrusion.
nLayers 1;
As this is a 2D case we must use 1 layer

linearNormalCoeffs • Remember, the utility extrudeMesh (step 4) reads the dictionary


{ extrudeMeshDict, which is located in the directory system.
Thickness of the extrusion.
thickness 1;
It is highly recommended to use a value of 1
} • Also remember to set the empty patches in the dictionary boundary and in the
boundary conditions.
mergeFaces false;
443 444

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


Exercises
• To get a feeling of the surface refinement, try to change the value of the surface refinement in • Meshing with snappyHexMesh – Case 5.
the dictionary snappyHexMeshDict.
• Mixing elbow (internal mesh)
• In the dictionary snappyHexMeshDict, change the value of nCellsBetweenLevels and
resolveFeatureAngle. What difference do you see in the output? • You will find this case in the directory:
• Use paraview to get a visual representation of the feature angles.
• In the dictionary snappyHexMeshDict, try to add curvature based refinement.
• In the dictionary snappyHexMeshDict, in the section addLayersControls change the value
of featureAngle. Use a value of 60 and 160 and compare the boundary layer meshing.
$PTOFC/101SHM/M2_mixing_elbow
• To control the boundary layer collapsing, try to use a uniform surface refinement. For this you
have two options, set surface level refinement to a uniform value or adding distance region
refinement at the wall.
• To control the boundary layer collapsing, try to use absolute sizes when creating the boundary
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
layer mesh. how to run the case. In this file, you might also find some additional comments.
• To get a feeling of the regions refinement, try to change the value of the local refinement in the • You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
dictionary snappyHexMeshDict. What difference do you see in the output? run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
• Try to use local inflation layers in the regions defined. automatically by typing in the terminal, for example, sh run_solver.
• In the dictionary extrudeMeshDict, change the value of nLayers and thickness. • We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this
• In the dictionary extrudeMeshDict, try to change the extrudeModel. 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.
445 446
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
Mixing elbow. Mixing elbow.
• How do we control surface refinement using region refinement?
• In the file snappyHexMeshDict, look for the following entry:

castellatedMeshControls
{
...
...
...

refinementRegions
{
mixing_elbow Name of surface
{
mode distance; Refinement using distance mode
levels ((1e-4 1));
}
}

... Distance from Refinement level


the surface patch
...
...
Your final mesh should looks like this one }
447 448

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


Mixing elbow. Mixing elbow.
• In this case we are going to generate a body fitted mesh with edge
refinement and boundary layer meshing. • At this point, we are going to work in parallel (but you can work in serial as
• This is an internal mesh. well).
• These are the dictionaries and files that will be used. • To generate the mesh, in the terminal window type:
• system/snappyHexMeshDict
1. $> foamCleanTutorials
• system/surfaceFeatureExtractDict
2. $> surfaceFeatureExtract
• system/meshQualityDict
3. $> blockMesh
• system/blockMeshDict
4. $> decomposePar
• constant/triSurface/surfacemesh.stl
5. $> mpirun -np 4 snappyHexMesh –parallel –overwrite
• constant/triSurface/surfacemesh.eMesh
6. $> mpirun -np 4 checkMesh –parallel –latestTime
7. $> reconstructParMesh -constant
• The file surfacemesh.eMesh is generated after using the utility
8. $> paraFoam
surfaceFeatureExtract, which reads the dictionary
surfaceFeatureExtractDict.
449 450
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
Mixing elbow. Mixing elbow.
• So what did we do? • After running checkMesh, you will get the following information regarding the patch
• Step 4: we distribute the mesh among the processors we want to use. names:
• Step 5 and 6: we run in parallel.
Patch Faces Points Surface topology
• Step 7: we put back together the decomposed mesh. mixing_elbow_inlet1 1264 1297 ok (non-closed singly connected)
pipe 38884 41118 ok (non-closed singly connected)
• Step 8: we visualize the reconstructed mesh. mixing_elbow_inlet2 314 337 ok (non-closed singly connected)
mixing_elbow_outlet 1264 1297 ok (non-closed singly connected)

• Notice that the utility blockMesh does not run in parallel.


• Remember to set the keyword numberOfSubdomains in the dictionary decomposeParDict • Sometimes you can get empty patches.
equal to the number of processors you want to use.
• In this case, as we are using 4 processors with mpirun, numberOfSubdomains needs to be Patch Faces Points Surface topology
minX 0 0 ok (empty)
equal to 4. maxX 0 0 ok (empty)
minY 0 0 ok (empty)
• To run the simulation and after reconstructing the mesh, you will need to transfer the boundary maxY 0 0 ok (empty)
and initial conditions information to the decomposed mesh, minZ 0 0 ok (empty)
maxZ 0 0 ok (empty)
• $> decomposePar –fields mixing_elbow_inlet1 1264 1297 ok (non-closed singly connected)
pipe 38884 41118 ok (non-closed singly connected)
• Or you can force to decompose everything as follows, mixing_elbow_inlet2 314 337 ok (non-closed singly connected)
mixing_elbow_outlet 1264 1297 ok (non-closed singly connected)
• $> decomposePar –force
451 452

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


Mixing elbow. Mixing elbow.
• Empty patches are no problem, they remain from the background mesh.
• The mesh used in the previous case was a STL with multiple surfaces.
• 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 • In you do not create the regions in the geometry section of the dictionary
snappyHexMeshDict, snappyHexMesh will automatically assign the names of the
parallel):
surface patches as follows:
• $> createPatch -overwrite system/surfaceFeatureExtractDict


• mixing_elbow_outlet …
• The surface patch pipe was created in the geometry section of the dictionary
snappyHexMeshDict. • mixing_elbow_inlet1 geometry
{
surfacemesh.stl

• The patches mixing_elbow_outlet, mixing_elbow_inlet1 and • mixing_elbow_inlet2 {


type triSurfaceMesh;
mixing_elbow_inlet2 were created automatically by snappyHexMesh. name mixing_elbow;
regions
{
• You have the choice of giving the names of the patches yourself or letting pipe NOTE 1
{
snappyHexMesh assign the names automatically. NOTE 2 name pipe;
}
• Remember, when creating the boundary layer mesh, these are the names you need }
}
to use to assign the layers. 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.

453 454
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
Mixing elbow. Mixing elbow.

• The mesh used in the previous case was a STL with multiple surfaces. • 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 • In the directory geometry, you fill find the file
snappyHexMeshDict, snappyHexMesh will automatically assign the names of the
mixing_pipe_onesurface.stl, this STL has one single surface.
surface patches as follows:
constant/triSurfaceSurfacemesh.stl
• Try to use this STL file to generate the mesh.
• mixing_elbow_outlet • You will notice that the final mesh has only one patch, namely
solid outlet
• mixing_elbow_inlet1 …

mixing_elbow (or whatever name you chose).

• mixing_elbow_inlet2 solid outlet • Also, it is not possible to have local control on the mesh refinement and
solid inlet1

boundary layer meshing.


solid inlet1
• You will also face the conundrum that as there is only one surface patch, it is
solid inlet2
not possible to assign boundary conditions.



solid inlet2

455 456

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


Mixing elbow. Exercises
• To solve the problem of the single surface patch, you can use the utility autoPatch. • To get a feeling of the includedAngle value, try to change the value in the dictionary
To do so, you can proceed as follows: surfaceFeatureExtractDict.
• $> autoPatch 60 -overwrite • Remember the higher the includedAngle value, the more features you will capture.
• In the dictionary snappyHexMeshDict, change the value of resolveFeatureAngle
• The option -overwrite, will copy the new mesh in the directory (try to use a lower value), and check the mesh quality in the intersection between
constant/polyMesh. both pipes.
• The utility autoPatch will use an angle criterion to find the patches, and will assign • In the castellatedMeshControls section, try to disable or modify the distance
the name auto0, auto1, auto2 and auto3 to the new patches. refinement of the mixing_elbow region (refinementRegions).
• What difference do you see in the output?
• The angle criterion is similar to that of the utility surfaceFeatureExtract.
• 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.
457 458
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh
• Meshing with snappyHexMesh – Case 6.
• Parallel meshing of a continuous stirring tank reactor mesh with moving
regions (internal mesh)
• You will find this case in the directory:

$PTOFC/101SHM/M3_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, • In this case we are going to use multiple STL and eMesh files.
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. • Each color in the figure above represents a different STL.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this • Working with multiple STL is no different from working with a single STL, we just need
way, you will get used with the command line interface and OpenFOAM® commands. to read all the STLs.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
• When working with multiple STL we have more control on the local refinement.
459 460

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
Inner region (rotating mesh) • In this case we are going to generate a body fitted mesh with two regions and using multiple
STL files.
Impeller • For simulation purposes, one of the regions will be in motion.
• This is an internal mesh.
• These are the dictionaries and files that will be used.
• system/snappyHexMeshDict
• system/meshQualityDict
• system/surfaceFeatureExtractDict
• system/decomposeParDict
• system/blockMeshDict
http://www.wolfdynamics.com/training/meshing/image5.gif • constant/triSurface/impeller.stl
• constant/triSurface/impeller.eMesh
• constant/triSurface/inner_volume.stl
• We are going to work with sliding grids (the impeller will be rotating), therefore we • constant/triSurface/inner_volume.eMesh
need to divide the mesh in two regions, one fix region and one rotating region. • constant/triSurface/shaft.stl
• constant/triSurface/shaft.eMesh
• To split the mesh in two regions we are going to use another STL file (the green • constant/triSurface/sparger.stl
surface), plus a few utilities to manipulate the mesh. • constant/triSurface/sparger.eMesh
• constant/triSurface/vesel.stl
• We will show how to setup conforming patches between regions.
• constant/triSurface/vesel.eMesh
461 462
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh

• At this point, we are going to work in parallel. • Let us take a look at the dictionary surfaceFeatureExtractDict.
• To generate the mesh, in the terminal window type: • Notice that we are reading multiple STL files.

1. $> foamCleanTutorials vessel.stl Name of the STL.


{
2. $> surfaceFeatureExtract }
… Edge detection parameters.

sparger.stl
3. $> blockMesh {

}
4. $> decomposePar shaft.stl Note:
{
$> mpirun -np 4 snappyHexMesh –parallel –overwrite … An individual eMesh file will be generated
5. } for each individual STL. That is:
inner_volume.stl
6. $> mpirun -np 4 checkMesh –parallel –latestTime {
… vessel.stl → vessel.eMesh
sparger.stl → sparger.eMesh
7. $> reconstructParMesh -constant }
impeller.stl shaft.stl → shaft.eMesh
{ Inner_volume.stl → inner_volume.eMesh
8. $> paraFoam …
impeller.stl → impeller.eMesh
}

463 464

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
• Let us take a look at the geometry section of the dictionary snappyHexMeshDict. • Let us take a look at the castellatedMeshControls section of the dictionary
• Notice that we are reading multiple STL files. snappyHexMeshDict.
• Notice that we are reading multiple eMesh files.
geometry
{
vessel.stl STL file to read. castellatedMeshControls
{ {
type triSurfaceMesh; ...
name vessel; Name of the surface inside snappyHexMesh. ...
Use regions if you have a STL ...
regions
with multiple patches defined.
{ //Explicit feature edge refinement
This is the name of the region or surface
inlet features
patch in the STL file .
User-defined patch name. { (
This is the final name of the name inlet; {
patch. } file ”vessel.eMesh"; Define every single eMesh file that
outlet level 0; you want to use.
{ }
name outlet; {
} Define every single eMesh file that
file ”shaft.eMesh";
} you want to use.
level 0;
} }
inner_volume.stl Define every single STL that
you want to use. ...
{ ...
type triSurfaceMesh; ...
name inner_volume;
} );
… }

}
465 466
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
• Let us take a look at the castellatedMeshControls section of the dictionary • Using paraFoam let’s take a look at the newly created zone.
snappyHexMeshDict.
• In this block we define the cellZone and faceZone, as follows,
face_inner_volume cell_inner_volume

castellatedMeshControls
{
...
...
...

//Surface based refinement Using the surface inner_volume we create a


inner_volume mesh zone that we will use at a later time to
( split the whole mesh in two regions.
level (1 1);

cellZone cell_inner_volume; Name of the cellZone.


faceZone face_inner_volume; Name of the faceZone.
cellZoneInside insidePoint; Use an inner point to define location of the zone
insidePoint (50 0 100); Location of the insidePoint.
); The point is located inside the surface
...
inner_volume, therefore the new zone is
...
... created inside the surface selected.
}

467 468

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh

• To visualize the zones in paraFoam you will need to enable the option • At this point and if you run checkMesh, you will get the following
Include Zones information:
• Then select the mesh parts cell_inner_volume and face_inner_volume. • $> checkMesh


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


• As you can see we only have one region, but we are interested in having
1. 2. two regions.
469 470
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh

• So far we only generated the mesh. • The utility createBaffles, reads the dictionary createBafflesDict.
• The next step will consist in splitting the mesh in two regions. • With this utility we create the interface patches between the fix zone and the
• Let us now create the two regions. rotating zone.

• We will use the following dictionaries and files:


baffles
{
rotating Name of the baffle group
• system/createBafflesDict {
type faceZone; Use faceZone
zoneName face_inner_volume; Face to use to construct the AMI patches.

• system/createPatchDict patches
{
The nanme was defined in snappyHexMeshDict

master Parameters for the master patch


• system/topoSetDict {
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 noOrdering;

• The utility createBaffles, reads the dictionary createBafflesDict.


}
slave Parameters for the slave patch
{
Boundary condition name AMI2; Name of the slave patch (user defined)
• The utility createPatch, reads the dictionary createPatchDict. for sliding grids
type cyclicAMI;
matchTolerance 0.0001;
neighbourPatch AMI1; Neighbour patch (master patch or AMI1)
• The utility topoSet, reads the dictionary topoSetDict. }
transform noOrdering;

}
}
} The master and slave patches
471 share a common face 472

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
• So what did we do?
• To create the two regions we proceed as follows (notice that we are going to • Step 1:
work in serial from now on)
• Splits the mesh in regions using the baffles (faceZone), created during the meshing
stage.
• We also create the cyclicAMI patches AMI1 and AMI2.
1. $> createBaffles –overwrite
• At this point we have two regions and one zone. However, the two regions are stich
2. $> mergeOrSplitBaffles –split –overwrite together via the patches AMI1 and AMI2.
3. $> createPatch –overwrite • Step 2: topologically split the patches AMI1 and AMI2. As we removed the link between
AMI1 and AMI2, the regions are free to move.
4. $> splitMeshRegions –makeCellZones –overwrite
• Step 3 (optional): gets rid of zero faced patches if hey exist. These are the patches
5. $> splitMeshRegions –detectOnly remaining from the base mesh, as they are empty, we do not need them.
6. $> transformPoints –scale ‘(0.01 0.01 0.01)’ • Step 4 (optional):
• Splits mesh into multiple zones. It will create automatically the sets and zones.
• At this point we have two regions and two zones.
• Step 5 (optional): just to show the regions and names.
• Step 6 (optional): scales the mesh.

473 474
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
• At this point and if you run checkMesh, you will get the following information: • 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.
• $> checkMesh
• In the dictionary constant/dynamicsMeshDict we set which region will move and the
… rotation parameters.

… • To preview the region motion, in the terminal type:
Checking topology… • $> moveDynamicMesh -checkAMI –noFunctionObjects
Boundary definition OK.
Cell to face addressing OK. • The command moveDynamicMesh –checkAMI will print on screen the quality of the AMI
Point usage OK. interfaces for every time step.
UPPER triangular ordering OK.
Face vertices OK. • Ideally, you should get the AMI patches weights as close as possible to one.
*Number of regions: 2
The mesh has multiple regions which are not connected by any face.
• Weight values close to one will guarantee a good interpolation between the AMI patches.
<<Writing region information to ”0/cellToRegion”
<<Writing region 0 with 136187 cells to cellSet region0
<<Writing region 1 with 67682 cells to cellSet region1 … Name of the AMI patch Name of the AMI patch

… 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

• As you can see, we now have two regions. AMI: Patch source sum(weights) min/max/average = 0.94746705, 1.0067199, 0.99994232 AMI1 patch weights

• At this point the mesh is ready to use. AMI: Patch target sum(weights) min/max/average = 0.94746692, 1.0004497, 0.99980782 AMI2 patch weights

• You can visualize the mesh (with all the sets and zones) using paraFoam. 475

476

snappyHexMesh guided tutorials snappyHexMesh guided tutorials


Ahmed body
• Meshing with snappyHexMesh – Case 7.
• Ahmed body (external mesh).
• You will find this case in the directory:

$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 • At this point, we all have a clear idea of how snappyHexMesh works.
way, you will get used with the command line interface and OpenFOAM® commands.
• If not, please raise your hand.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
• So let us go free styling and let us play around with this case.
477 478
snappyHexMesh guided tutorials Roadmap
Ahmed body
• In our YouTube channel you will find a playlist with many videos for this case. The playlist is
titled: CFD workflow tutorial using open-source tools. 1. Meshing preliminaries
• You can find our YouTube channel in the following link:
https://www.youtube.com/channel/UCNNBm3KxVS1rGeCVUU1p61g 2. What is a good mesh?
• In these videos, we show a few extra features and some tips and tricks to take the most out of
snappyHexMesh. 3. Mesh quality assessment in OpenFOAM®
• If you get lost, read the REAME.FIRST file that you will find in the working directory.
• The dictionaries snappyHexMeshDict and blockMeshDict used in this case are very 4. Mesh generation using blockMesh.
clean and ready to use. So feel free to use them as your templates.
• Our best advice is not to get lost in all the options available in the dictionary 5. Mesh generation using snappyHexMesh.
snappyHexMeshDict. Most of the times the default options will work fine.
• That being said, you only need to read in the geometries, set the feature edges and surface 6. snappyHexMesh guided tutorials.
refinement levels, choose in which surfaces you want to add the boundary layers, and choose
how many layers you want to add. 7. Mesh conversion
• Final advices:
• If you are working with a complicated geometry, add one layer at a time. 8. Geometry and mesh manipulation utilities
• Use paraFoam/paraview to get visual references.
• Always check the quality of your mesh.

479 480

Mesh conversion Mesh conversion


• OpenFOAM® gives users a lot of flexibility when it comes to meshing. • In the directory $FOAM_UTILITIES/mesh/conversion you will find the source
• You are not constrained to use OpenFOAM® meshing tools. code for the mesh conversion utilities:
• To convert a mesh generated with a third-party software to OpenFOAM® polyMesh format, you
• ansysToFoam • kivaToFoam
can use the OpenFOAM® mesh conversion utilities.
• If your format is not supported, you can write your own conversion tool.
• cfx4ToFoam • mshToFoam
• By the way, many of the commercially available meshers can save the mesh in OpenFOAM® • datToFoam • netgenNeutralToFoam
polyMesh format or in a compatible format. • fluent3DMeshToFoam • Optional/ccm26ToFoam
• In the directory $PTOFC/mesh_conversion_sandbox you will find a few meshes generated • fluentMeshToFoam • plot3dToFoam
using the most popular third-party mesh generation applications.
• foamMeshToFluent • sammToFoam
• 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
• foamToStarMesh • star3ToFoam
mesh. • foamToSurface • star4ToFoam
• Remember to always check the file boundary after converting the mesh. You • gambitToFoam • tetgenToFoam
will need to change the name and type of the surface patches according to what • gmshToFoam • vtkUnstructuredToFoam
you would intent to do.
• ideasUnvToFoam • writeMeshObj
• 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. • 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.
481 482
Mesh conversion Mesh conversion
Case 1. Mixing elbow (internal mesh).

• Remember to export the mesh in UNV format in Salome.


• Let us convert to OpenFOAM® format a mesh generated using Salome.
• Then use the utility ideasUnvToFoam to convert the mesh to OpenFOAM® native
• You will find this case in the directory: format.
• In the terminal window type:

$PTOFC/mesh_conversion_sandbox/M1_mixing_elbow_salome 1. $> foamCleanTutorials


2. $> foamCleanPolyMesh
3. $> ideasUnvToFoam ../../meshes_and_geometries/salome_elbow3d/Mesh_1.unv

4. $> checkMesh
• 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. 5. $> paraFoam
• 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.
• Remember to always check the file boundary after converting the mesh.
• 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. • To convert the mesh, you need to be in the top level of the case directory and you
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases. need to give the path (absolute or relative) of the mesh to be converted.
483 484

Mesh conversion Mesh conversion


Case 1. Mixing elbow (internal mesh). Case 1. Mixing elbow (internal mesh).
• ideasUnvToFoam output. • checkMesh output.

Create time Mesh stats


points: 31136
Processing tag:2411 faces: 312414
Starting reading points at line 3.
Read 31136 points. internal faces: 291842
cells: 151064
Processing tag:2412 faces per cell: 4
Starting reading cells at line 62278. boundary patches: 4
First occurrence of element type 11 for cell 1 at line 62279
First occurrence of element type 41 for cell 361 at line 63359 point zones: 0
First occurrence of element type 111 for cell 20933 at line 104503 face zones: 0
Read 151064 cells and 20572 boundary faces. Internal cells and boundary faces read cell zones: 0
Processing tag:2467
Starting reading patches at line 406633. Overall number of cells of each type:
For group 1 named pipe trying to read 19778 patch face indices. hexahedra: 0
For group 2 named inlet1 trying to read 358 patch face indices. prisms: 0
For group 3 named inlet2 trying to read 78 patch face indices. wedges: 0
For group 4 named outlet trying to read 358 patch face indices.
pyramids: 0
Sorting boundary faces according to group (patch) tet wedges: 0
0: pipe is patch tetrahedra: 151064
1: inlet1 is patch polyhedra: 0
2: inlet2 is patch
3: outlet is patch
Checking topology...
Constructing mesh with non-default patches of size: Boundary definition OK.
pipe 19778 Cell to face addressing OK.
inlet1 358
inlet2 78 Boundary patches detected Point usage OK.
outlet 358 Upper triangular ordering OK.
Face vertices OK.
End Number of regions: 1 (OK).

485 486
Mesh conversion Mesh conversion
Case 1. Mixing elbow (internal mesh). Case 1. Mixing elbow (internal mesh).
• checkMesh output. • The boundary file.

4 Number of boundary patches


Checking patch topology for multiply connected surfaces... (
Patch Faces Points Surface topology pipe
{
Name of the boundary patches
pipe 19778 9938 ok (non-closed singly connected)
inlet1 358 200 ok (non-closed singly connected) type patch;
inlet2 78 50 ok (non-closed singly connected) nFaces 19778;
outlet 358 200 ok (non-closed singly connected) startFace 291842; • In this case, the utility recognized the
}
Checking geometry... inlet1 name of the boundary patches.
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)
type
nFaces
patch;
358;
• If you do not like the names feel free to
Boundary openness (-1.0302e-17 -6.17232e-17 -1.77089e-16) OK.
}
startFace 311620; change them.
Max cell openness = 2.32045e-16 OK.
inlet2
Max aspect ratio = 4.67245 OK.
Minimum face area = 0.000286852. Maximum face area = 0.010949. Face area magnitudes OK. { • Remember, do not use spaces of
Min volume = 2.74496e-06. Max volume = 0.00035228. Total volume = 6.75221. Cell volumes OK. type patch;
Mesh non-orthogonality Max: 54.2178 average: 15.1295 nFaces 78;
strange symbols.
Non-orthogonality check OK. startFace 311978;
Face pyramids OK. }
Max skewness = 0.649359 OK. outlet
Coupled point location match (average 0) OK. {
type patch;
Mesh OK. Everything is OK nFaces 358;
startFace 312056;
End }
)

487 488

Mesh conversion Roadmap


Case 1. Mixing elbow (internal mesh).
• The boundary file.
1. Meshing preliminaries
4
(
pipe
2. What is a good mesh?
{
type
nFaces
patch;
19778;
Base type of the boundary patches 3. Mesh quality assessment in OpenFOAM®
startFace 291842;
}
inlet1 • In this case, the utility automatically 4. Mesh generation using blockMesh.
{
type patch; assigned the base type patch to all
nFaces
startFace
358;
311620; boundary patches. 5. Mesh generation using snappyHexMesh.
}
inlet2
{
• Feel free to change the base type 6. snappyHexMesh guided tutorials.
type
nFaces
patch;
78;
according to your needs.
}
startFace 311978;
• In this case, it will be wise to change 7. Mesh conversion
outlet
the base type of patch pipe to wall.
{
type patch; 8. Geometry and mesh manipulation utilities
nFaces 358;
startFace 312056;
}
)

489 490
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
• First of all, by mesh manipulation we mean modifying a valid OpenFOAM® • In the directory $FOAM_UTILITIES/mesh/manipulation you will find the
mesh. following mesh manipulation utilities.
• Inside each utility directory you will find a *.C file with the same name as the
• These modifications can be scaling, rotation, translation, mirroring,
directory. This is the main file, where you will find the top-level source code and a
topological changes, mesh refinement and so on.
short description of the utility.
• In the directory $FOAM_UTILITIES/mesh/manipulation you will find the • For instance, in the directory checkMesh, you will find the file checkMesh.C, which
mesh manipulation utilities. Just to name a few: is the source code of the utility checkMesh. In the source code you will find the
following description:
• autoPatch • rotateMesh
• checkMesh • setSet Checks validity of a mesh.

• createBaffles • splitMesh Usage


- checkMesh [OPTION]
• mergeMeshes • splitMeshRegions
\param -allGeometry \n
• mergerOrSplitBaffles • stitchMesh Checks all (including non finite-volume specific) geometry

• mirrorMesh • subsetMesh \param -allTopology \n


Checks all (including non finite-volume specific) addressing
• polyDualMesh • topoSet \param -meshQuality \n
• refineMesh • transformPoints Checks against user defined (in \a system/meshQualityDict) quality settings

\param -region \<name\> \n


• renumberMesh Specify an alternative mesh region.
491 492

Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
• In OpenFOAM® it is also possible to manipulate the geometries in STL • In the directory $FOAM_UTILITIES/surface you will find the following surface
format. manipulation utilities.

• These modifications can be scaling, rotation, translation, mirroring, • 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
topological changes, normal orientation, and so on.
short description of the utility.
• In the directory $FOAM_UTILITIES/surface you will find the mesh
• For instance, in the directory surfaceTransformPoints, you will find the file
manipulation utilities. Just to name a few: surfaceTransformPoints.C, which is the source code of the utility
surfaceTransformPoints. In the source code you will find the following
• surfaceAdd • surfaceMeshConvert description:
• surfaceAutoPatch • surfaceMeshExport
• surfaceBooleanFeatures • surfaceMeshTriangulate Transform (scale/rotate) a surface.
• surfaceCheck • surfaceOrient Like transformPoints but for surfaces.

• surfaceConvert • surfaceSplitByPatch The rollPitchYaw option takes three angles (degrees):


- roll (rotation about x) followed by
• surfaceFeatureConvert • surfaceSubset
- pitch (rotation about y) followed by
• surfaceFeatureExtract • surfaceToPatch - yaw (rotation about z)
• surfaceInertia • surfaceTransformPoints The yawPitchRoll does yaw followed by pitch followed by roll.

493 494
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM®
• Let us do some surface manipulation. • We will now manipulate a STL geometry. In the terminal type:
• For this we will use the ahmed body tutorial.
1. $> foamCleanTutorials
• You will find this case in the directory:
2. $> surfaceMeshInfo ./constant/triSurface/ahmed_body.stl
3. $> surfaceCheck ./constant/triSurface/ahmed_body.stl
$PTOFC/mesh_quality_manipulation/M5_ahmed_body_transform
$> 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)'
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of 6. ./constant/triSurface/ahmed_body.stl scaled.stl
how to run the case. In this file, you might also find some additional comments.
$> surfaceInertia -density 2700 –noFunctionObjects
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh, 7. ./constant/triSurface/ahmed_body.stl
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. $> surfaceOrient ./constant/triSurface/ahmed_body_wrong_normals.stl
8. out.stl ‘(1e10 1e10)’
• 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.
495 496

Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM® Geometry manipulation in OpenFOAM®
• In step 2 we use the utility surfaceMeshInfo to get general information about the STL (such • Pay particular attention to step 8.
as number of faces and so on). • We already have seen that snappyHexMesh computes surface angles using the surface
• In step 3 we use the utility surfaceCheck to check the STL file. normals as a reference, so it is extremely important to have the normals oriented in the same
• In step 4 we use the utility surfaceTransformPoints to rotate the STL. We read in the STL way and preferably outwards.
./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
ahmed_body_wrong_normals.stl STL after orienting all normals in the same
this point is outside the STL all normals will be oriented outwards, if the point is inside the STL direction.
all normals will be oriented inwards.
497 498
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Geometry manipulation in OpenFOAM®
• To plot the normals in paraview/paraFoam you can use the filter Normal Glyphs • Let us do some mesh manipulation.
Select the Normal Glyphs from the filter menu
• For this we will use the 2D cylinder tutorial.
• You will find this case in the directory:

Apply the Normal Glyphs


filter to the STL $PTOFC/mesh_quality_manipulation/M7_cylinder_transform

Uncheck this option • 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.
Scale the vectors to fit the screen
• 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.
499 500

Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Mesh manipulation in OpenFOAM® 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
Original mesh
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 After renaming the patches and transforming the mesh, we can
system/createPatchDict. Instead of using the utility createPatch we could have modified the use it to conduct this buoyant flow simulation
www.wolfdynamics.com/wiki/heated_cyl/ani1.gif
boundary file directly.
• This case is ready to run using the solver buoyantBoussinesqPimpleFoam. 501 Transformed mesh 502
Roadmap

Module 4
1. Running in parallel
Running in parallel

503 504

Running in parallel Running in parallel


• First of all, to know how many processors/cores you have available in your computer, • OpenFOAM® does not take advantage of hyper threading technology (HT).
type in the terminal: • HT is basically used by the OS to improve multitasking performance.
• $> lscpu
• This is what we have in the workstation of the previous example:
• The output for this particular workstation is the following: • 24 virtual cores (hyper threaded)
Architecture: x86_64
• 12 physical cores
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:
Thread(s) per core:
0-23
2
• To take full advantage of the hardware, we use the maximum number of physical
Core(s) per socket:
Socket(s):
6
2
Number of threads per core (hyper threading) cores (12 physical cores in this case) when running in parallel.
NUMA node(s):
Vendor ID:
2
GenuineIntel Number of cores per socket or physical
• If you use the maximum number of virtual cores, OpenFOAM® will run but it will be
CPU family: 6
Model: 44
processor slower in comparison to running with the maximum number of physical cores (or even
Model name:
Stepping:
Intel(R) Xeon(R) CPU
2
X5670 @ 2.93GHz
Number of sockets (physical processors)
less cores).
CPU MHz: 1600.000
CPU max MHz: 2934.0000 • Same rule applies when running in clusters/super computers, so always read the
CPU min MHz: 1600.0000
BogoMIPS: 5851.91 hardware specifications to know the limitations.
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

This is what makes a processor expensive


505 506
Running in parallel Running in parallel
Why use parallel computing? Speed-up and scalability example
• Solve larger and more complex problems (scale-up):
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).

• Provide concurrency (scale-out):


A single computer or processor can only do one thing at a time. Multiple processors or computing
resources can do many things simultaneously.

• Save time (speed-up):


Run faster (speed-up) and increase your productivity, with the potential of saving money in the design
process.
• In the context of high performance computing (HPC), there are two common metrics that measure the scalability
• Save money: of the application:
• Strong scaling (Amdahl’s law): which is defined as how the solution time varies with the number of
In theory, throwing more resources at a task will shorten its time to completion, with potential cost processors for a fixed problem size (number of cells in CFD)
savings. Parallel computers can be built from cheap, commodity components.
• Weak scaling (Gustafson’s law): which is defined as how the solution time varies with the number of
• Limits to serial computing: processors for a fixed problem size per processor (or increasing the problem size with a fix number of
processors).
Both physical and practical reasons pose significant constraints to simply building ever faster serial • In this example, when we reach 12 cores inter-processor communication slow-downs the computation. But if we
computers (e.g, transmission speed, CPU clock rate, limits to miniaturization, hardware cooling). 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
507 MPI library. 508

Running in parallel Running in parallel


• The method of parallel computing used by OpenFOAM® is known as domain Some facts about running OpenFOAM® in parallel:
decomposition, in which the geometry and associated fields are broken into pieces
and distributed among different processors. • Applications generally do not require parallel-specific coding. The
parallel programming implementation is hidden from the user.
• In order to run in parallel you will need an MPI library installation in your
system.
• Most of the applications and utilities run in parallel.
• If you write a new solver, it will be in parallel (most of the times).
Shared memory architectures – Workstations and portable computers • We have been able to run in parallel up to 15000 processors.
• We have been able to run OpenFOAM® using single GPU and multiple
GPUs.
• Do not ask about scalability, that is problem/hardware specific.
• If you want to learn more about MPI and GPU programming, do not look
in my direction.
Distributed memory architectures – Clusters and super computers • And of course, to run in parallel you need the hardware.
509 510
Running in parallel Running in parallel
To run OpenFOAM® in parallel you will need to: Domain Decomposition in OpenFOAM®
• The mesh and fields are decomposed using the decomposePar utility.
• Decompose the domain. • They are broken up according to a set of parameters specified in a dictionary named
decomposeParDict that is located in the system directory of the case.
To do so we use the decomposePar utility. You also need the dictionary
decomposeParDict which is located in the system directory. • In the decomposeParDict dictionary the user must set the number of domains in
which the case should be decomposed (using the keyword numberOfSubdomains).
The value used should correspond to the number of physical cores available.
• Distribute the jobs among the processors or computing nodes.
To do so, OpenFOAM® uses the standard message passing interface (MPI).
By using MPI, each processor runs a copy of the solver on a separate part numberOfSubdomains 128; Number of subdomains
of the decomposed domain. method scotch; Decomposition method

• Additionally, you might want to reconstruct (put back together) the


decomposed domain.
• In this example, we are subdividing the domain in 128 subdomains, therefore we
This is done by using the reconstrucPar utility. You do not need a should have 128 physical cores available.
dictionary to use this utility.
• The main goal of domain decomposition is to minimize the inter-processors
511 communication and the processor workload. 512

Running in parallel Running in parallel


Domain Decomposition Methods Running in parallel – Gathering all together
• These are the decomposition methods available in OpenFOAM® 6
• hierarchical The information inside the
directories polyMesh/ and
• manual 0/ is decomposed using the
utility decomposePar
• metis
• multiLevel decomposePar
• 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

processor0 processor1 processor2 processor3


• If you want more information about each decomposition method, just read
the source code:
• $WM_PROJECT_DIR/src/parallel/decompose/ • Inside each processorN directory you will have the mesh information, boundary conditions,
initial conditions, and the solution for that processor.
513 514
Running in parallel Running in parallel
Running in parallel – Gathering all together Running in parallel – Gathering all together
• After decomposing the mesh, we can run in parallel using MPI. • 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

$> mpirun –np <NPROCS> <application/utility> –parallel • When you reconstruct the case, you glue together
all the information contained in the decomposed
case.
• The number of processors to use or <NPROCS>, needs to be the same as the • All the information (mesh, boundary conditions,
number of partitions (numberOfSubdomains). initial conditions, and the solution), is transfer to
• Do not forget to use the flag –parallel. the original case folder (polyMesh and time
solution directories).
515 516

Running in parallel Running in parallel


Running in parallel – Gathering all together Kelvin Helmholtz instability in a coarse mesh
• Summarizing, to run in parallel we proceed in the following way:

1. $> decomposePar Processors Clock time (seconds)


Mesh size
in x, y, and z directions
2. $> mpirun –np <NPROCS> <application/utility> –parallel
1 955 800 X 160 X 1
3. $> reconstructPar
2 564 800 X 160 X 1

4 333 800 X 160 X 1

• You can do the post-processing and visualization on the decomposed case 8 234 800 X 160 X 1
or reconstructed case. We are going to address this later on.
12 244 800 X 160 X 1

• If you are doing remeshing or using AMR you will need to use
reconstructParMesh before reconstrucPar. Volume fraction
www.wolfdynamics.com/wiki/kelvin_helmholtz/ani1.gif

517 You will find this case in the directory: $PTOFC/parallel/kelvin_helmholtz 518
Running in parallel Running in parallel
Visualization of a parallel case Visualization of a parallel case

• The traditional way is to first reconstruct the case and then do the post- • An alternative way to visualize the solution, is by proceeding in the following
processing and visualization on the reconstructed case. way
• $> paraFoam –builtin
• To do so, we type in the terminal:
• The option –builtin let us post-process the decomposed case directly.
1. $> reconstructPar
• Remember, you will need to select on the object inspector the Decomposed
2. $> paraFoam Case option.

• 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.

519 520

Running in parallel Running in parallel


Visualization of a parallel case Decomposing big meshes
• One final word, the utility decomposePar does not run in parallel. So, it is
• Both of the previous methods are valid.
not possible to distribute the mesh among different computing nodes to do
• When we use the option –builtin with paraFoam, we have the option to the partitioning in parallel.
work on the decomposed case directly.
• That is to say, we do not need to reconstruct the case.
• If you need to partition big meshes, you will need a computing node with
• But wait, there is a third option. enough memory to handle the mesh. We have been able to decompose
• The third option consist in post-processing each decomposed domain meshes with up to 500.000.000 elements, but we used a computing node
individually. with 512 gigs of memory.
• To load all processor directories, you will need to manually create the file
processorN.OpenFOAM (where N is the processor number) in each • For example, in a computing node with 16 gigs of memory, it is not possible
processor folder. to decompose a mesh with 30.000.000. You will need to use a computing
• After creating all processorN.OpenFOAM files, you can launch paraFoam node with at least 32 gigs of memory.
and load each file (the processorN.OpenFOAM files).
• As you can see, this option requires more input from the user. • Same applies for the utility reconstructPar.

521 522
Running in parallel Running in parallel
Do all utilities run in parallel? Exercises
• Choose any tutorial or design your own case and do an scalability test. Scale your case with two different
• At this point, you might be wondering if all solvers/utilities run in parallel. meshes (a coarse and a fine mesh).
• Run the same case using different partitioning methods. Which method scales better? Do you get the same
• To know what solvers/utilities do not run in parallel, in the terminal type: results?
• $> find $WM_PROJECT_DIR -type f | xargs grep –sl ‘noParallel’ • 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
• Paradoxically, the utilities used to decompose the domain and reconstruct the cores. Which scenario is faster and why?
domain do not run in parallel. • Run a parallel case without using the –parallel option. Does it run? Is it faster of slower? How many
• Another important utility that does not run in parallel is blockMesh. So to generate outputs do you see on the screen?
• Do you get any speed-up by using renumberMesh?
big meshes with blockMesh you need to use a big fat computing node.
• What applications do not run in parallel?
• Another important utility that does not run in parallel by default is paraFoam.
• To compile paraFoam with MPI support, in the file makeParaView4 (located in the
directory $WM_THIRD_PARTY_DIR), set the option withMPI to true,
• withMPI = true
• While you are working with the file makeParaView4, you might consider enabling
Python support,
• withPYTHON = true

523 524

Roadmap

Module 5 1. On-the-fly postprocessing – functionObjects and the


postProcess utility
The postprocess utility – Sampling – Probing 2. Sampling with the postProcess utility
– On-the-fly postprocessing – Field 3. Field manipulation
manipulation – Data conversion 4. Data conversion

525 526
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
• In the directory $FOAM_SRC/functionObjects you will find the source code for the
• It is possible to perform data extraction/manipulation operations while the simulation functionObjects.
is running by using 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
• functionObjects are small pieces of code executed at a regular interval without name a few functionObjects:
explicitly being linked to the application.
• When using functionObjects, files of sampled data can be written for plotting and • corantNo • forceCoeffs
post processing. • div • forces
• functionObjects are specified in the controlDict dictionary and executed at pre- • fieldAverage • icoUncoupledKinematicCloud
defined intervals. • fieldMinMax • scalarTransport
• All functionObjects are runtime modifiable. • grad • codedFunctionObject
• Depending of the functionObject you are using, its output is saved in the directory • MachNo • residuals
postProcessing or in the solution directory (time directories). • Q • systemCall
• It is also possible to execute functionObject after the simulation is over, we will call • vorticity • timeActivatedFileUpdate
this running functionObject a-posteriori. • yPlus • writeObjects
• For example, you can use functionObjects to compute the Mach number, the
vorticity field, and to sample the velocity at given points or along a line, and • In addition to the functionObjects located in the directory $FOAM_SRC/functionObjects,
you can also run the sampling and co-processing utilities on-the-fly.
everything while the simulation is running.
• You will find the source code for the sampling and co-processing utilities in the directory
527 $FOAM_SRC/sampling. 528

On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects


• functionObjects are defined in the controlDict dictionary. • There are many functionObjects implemented in OpenFOAM®, and sometimes is
• To execute a functionObject you need to at least define the following entries: 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
function_object_name User given name how to use functionObjects.
type function_object_to_use; functionObject to use • Remember, the source code of the functionObjects is located in the directory:
$WM_PROJECT_DIR/src/postProcessing/functionObjects
functionObjectLibs ("function_object_library.so"); Library to use

enabled true; Turn on/off functionObject


• The source code of the sampling and co-processing utilities is located in the directory:
Show on screen the output of
log true;
the functionObject
$WM_PROJECT_DIR/src /sampling
writeControl outputTime;
timeStart 0; Output frequency
timeEnd 20;
• The source code of the database entries required for the functionObjects is located
in the directory:
// ... $FOAM_SRC/OpenFOAM/db/functionObjects
// functionObject Keywords and sub-dictionaries
// keywords and sub-dictionaries specific to the functionObject
// ...
• Here after we are going to study a few commonly used functionObjects.
529 530
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
At the end of the day, you should get something like this
• Let us do some on-the-fly postprocessing.
Qualitative post-processing Quantitative post-processing
• For this we will use the multi-element airfoil 2D case. cd cl

• You will find this case in the directory: Experimental values 0.0332 2.167

Numerical values 0.0346 2.238

$PTOFC/postprocessing/MDA_30P30N Additionally, by using functionObjects we will


compute many derived quantities, such as,
• yPlus.
• Voriticity.
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of • Mean values of the field variables (notice
how to run the case. In this file, you might also find some additional comments. that we will compute the average of a
steady solution).
• 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 • Forces.
automatically by typing in the terminal, for example, sh run_solver. • Force coefficients.
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this • Minimum and maximum values of the field
variables.
way, you will get used with the command line interface and OpenFOAM® commands.
• Sampling at given points.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
• Mass flow at inlets and outlets.
531 532

On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects


At the end of the day, you should get something like this At the end of the day, you should get something like this

Should I stop here? Or should I stop here?

Quantitative post-processing 533 Quantitative post-processing – Assessing residuals 534


On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
Running the case The controlDict dictionary
• Let us take a look at the bottom of the controlDict
• Let us run this case using the automatic scripts distributed with the tutorial. In the 51 functions dictionary file. In this dictionary is where we define all
52 {
terminal type: functionObjects.
name_of_the_functionObject_dictionary
{ • Within this dictionary, functionObjects are defined in
Sub-dictionary with functionObject entries
the sub-dictionary functions, i.e.,
1. $> sh run_all.sh }

198 #include "externalFunctionObject"


functions
• After the simulation is finish, you will find the decomposed directories (processor0, 200 }
{
processor1, processor2 and processor3), the postProcessing directory, functionObjects definition
};
and the 2000 directory. The solution, and output of the functionObjects, is saved in
these directories.
• In this case, the functionObjects are defined in lines
• Remember, to visualize the decomposed solution you will need to launch paraFoam 51-200 (the sub-dictionary functions).
as follows, • Each defined functionObject has its own name and its
compulsory keywords and entries.
• Notice that in line 198 we use the directive include to call
1. $> paraFoam -builtin an external dictionary with the functionObjects
definition.
• If you do not give the path of the external dictionary, the
solver will look for it in the directory system.
• Do not erase the solution as we are going to use it in the next section. • If you use the include directive, you will need to update
the controlDict dictionary in order to read any
535 modification done in the included dictionary files. 536

On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects


The controlDict dictionary The controlDict dictionary
• Let us explain in detail how to setup a functionObject. • Let us study all entries of the forces functionObject
51 functions 51 functions

56 forces_object functionObject identifier • As the names implies, this functionObject is used to 56 forces_object functionObject identifier (user given)
57 { (user given) compute the forces on a given body or set of bodies 57 {
58 type forces; 58 type forces;
(line 68). functionObject to use
59 functionObjectLibs ("libforces.so"); • You can add as many forces functionObjects (or any 59 functionObjectLibs ("libforces.so");
functionObject library to use
60 60
61 other one) as you like, but you should assign them 61
62
63
writeControl timeStep;
writetInterval 1;
different identifiers (line 56). Remember not to use 62
63
writeControl timeStep;
writetInterval 1;
Controls for saving frequency
64 white spaces when naming functionObjects. 64
65 enabled true; 65 enabled true; Turn on/off functionObject
66
67 //// Patches to sample
• The output of this functionObject is saved in the 66
67 //// Patches to sample
68 patches ("wall_slat" "wall_airfoil" "wall_flap"); directory postProcessing/forces_object, 68 patches ("wall_slat" "wall_airfoil" "wall_flap"); Compute the forces on these patches
where the directory name is taken from line 56.
70 //// Name of fields 70 //// Name of fields
71 pName p; • Inside this directory, you will find the subdirectory 0, 71 pName p;
Name of the velocity and pressure fields. If you use
72 Uname U; 72 Uname U; different fields, e.g., pMean and Umean, they need to be
which means that you started to sample data from time computed before this functionObject
0. If you start from a different time, you will find a
74 //only for incompressible flows different subdirectory, e.g., 86.05 74 //only for incompressible flows Reference density value. It only needs to be defined for
75 rho rhoInf; 75 rho rhoInf;
incompressible flows. For compressible flows, the
76 rhoInf 1.0; • Remember, different functionObjects will have 76 rhoInf 1.0;
computed density is used instead (you will need to define
different entries, to know the entries just refer to the a dummy value, though)
78 //// Centre of rotation online documentation or skim the source code, which 78 //// Centre of rotation
79 CofR (0 0 0); is located in the directory, 79 CofR (0 0 0);
Reference center of rotation to compute moments
80 } 80 }

200 }
• $WM_PROJECT_DIR/src/postProcessing/f 200 } Note:
unctionObjects • The source code of this functionObject is located in the directory
$FOAM_SRC/functionObjects/forces/forces
537 • Use the banana method to know all the options available for each entry. 538
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
The controlDict dictionary The controlDict dictionary
• Let us study now the functionObject used to • Let us study now the functionObject used to
51 functions functionObject 51 functions functionObject
compute the force coefficients. compute the force coefficients.
86 forceCoeffs_object
identifier (user given) 86 forceCoeffs_object
identifier (user given)
87 { 87 {
88 type forceCoeffs; 88 type forceCoeffs;
89 functionObjectLibs ("libforces.so"); 89 functionObjectLibs ("libforces.so");
90 90
91 enabled true; 91 enabled true;
92 • This functionObject computes the force coefficients. 92
93 patches ("wall_slat" "wall_airfoil" "wall_flap"); 93 patches ("wall_slat" "wall_airfoil" "wall_flap");
94
• These entries are similar to those of the force 94
95 pName p; functionObject 95 pName p;
96 Uname U; 96 Uname U;
97 97
99 rho rhoInf; 99 rho rhoInf;
100 rhoInf 1.0; 100 rhoInf 1.0;
101
This option will output the values to a text file located in the 101
103 log true; directory postProcessing/forceCoeffs_object 103 log true;
104 104
105 CofR (0.0 0 0); 105 CofR (0.0 0 0);
106 Reference center of rotation to compute moments 106
107 pitchAxis (0 0 1); 107 pitchAxis (0 0 1);
108 magUInf 1.0; 108 magUInf 1.0;
109 lRef 1; Reference values used to compute coefficients 109 lRef 1;
110 Aref 1; 110 Aref 1;
111 111
115 writeControl timeStep; 115 writeControl timeStep;
116 writeInterval 1;
Controls for saving frequency 116 writeInterval 1;
117 117
119 liftDir (0 1 0); 119 liftDir (0 1 0); • Reference axes to compute the lift and drag coefficients.
120 dragDir (1 0 0); Reference axes to compute the lift and drag coefficients. 120 dragDir (1 0 0);
121 121 • Remember, lift and drag are perpendicular and parallel
125 } 125 }
to the incoming flow, respectively.
196 } 196 }
• So if the inlet velocity is entering at a given angle, you
should adjust the vectors liftDir and dragDir so they are
aligned with the incoming flow (rotation matrix).
539 540

On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects


The controlDict dictionary The controlDict dictionary
• fieldMinMax functionObject
51 functions 51 functions • fieldAverage functionObject
• This functionObject is used to compute the minimum
131 minmaxdomain
and maximum values of the field variables. 166 fieldAverage1 • This functionObject is used to compute the
132 { 167 {
133 type fieldMinMax; 168 type fieldAverage; average values of the field variables.
134
• The output of this functionObject is saved in ascii format 169 libs ( "libfieldFunctionObjects.so" );
135 functionObjectLibs ("libfieldFunctionObjects.so"); in the file fieldMinMax.dat located in the directory 170 writeControl writeTime; • The output of this functionObject is saved in the
136 171 fields
137 enabled true; postProcessing/minmaxdomain/0 172 ( time solution directories.
138 173 U
139 mode component; • Remember, the name of the directory where the output 174 { • In this case, we are computing the field averages
140 175 mean on;
141 writeControl timeStep; data is saved is the same as the name of the 176 prime2Mean on; of velocity (U), pressure (p), and turbulent
142 writeInterval 1; functionObject (line 131). 177 base time;
viscosity (nut).
143 178 }
144 log true; 179
145 180 p • In this functionObject, prime2Mean is the
146 fields (p U nuTilda nut k omega); 181 {
147 }
• yPlus functionObject 182 mean on;
average of the product of the fluctuations of the
148
• This functionObject is used to compute the yPlus field.
182 prime2Mean on; variable,
149 184 base time;
150 185 }
151 • This functionObject has two outputs, one output saved 186
152 in the solution directories (1, 2, 3, and so on). You can 187 nut
153 yplus 188 {
154 { visualize this output using paraview/paraFoam. 189 mean on;
155 type yPlus; 190 prime2Mean on;
156 functionObjectLibs ("libfieldFunctionObjects.so"); • The second output is located in the directory 191 base time;
157 enabled true; 192 } • In line 198 we add functionObjects using an external
158 log true; postProcessing/yplus/0. 193 ); file. In this case, the functionObject is located in the
159 writeControl outputTime; 194 }
160 } • In this file you will find the minimum, maximum and directory system
198 #include “externalfunctionObject“
196 } average values of yPlus in all patches defined as walls.
196 }
• Remember, the name of the directory where the output
data is saved is the same as the name of the
functionObject (line 153).
541 542
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
The externalFunctionObject dictionary Final remarks on functionObjects

• probes functionObject
• A functionObject that is very useful, but we did not use in this case:
19 probes_online
20 {
21 type probes; • This functionObject is used to probe field data at the
22 functionObjectLibs ("libfieldFunctionObjects.so"); given locations. inlet_massflow
23 enabled true;
24 writeControl timeStep; • In this case, we are sampling the fields U and p (lines 35- {
25 writeInterval 1;
26 39) type surfaceRegion;
27 probeLocations functionObjectLibs ("libfieldFunctionObjects.so");
28 ( • The output of this functionObject is saved in ascii format
29 (1 0 0) in the files p and U located in the directory writeControl timeStep;
30 (2 0 0) writesInterval 1;
31 (2 0.25 0)
postProcessing/probes_online/0 log true;
32 (2 -0.25 0)
Compute functionObject in a boundary patch
33 );
• Remember, the name of the directory where the output writeFields false;
34
35 fields data is saved is the same as the name of the regionType patch;
36 (
functionObject (line 19). name inlet;
37 U
38 p operation sum;
Compute functionObject in this boundary patch
39 ); fields (phi);
40
41 } • vorticity functionObject }
47 vorticity • This functionObject is used to compute the vorticity field.
48 {
49 type vorticity; • The output of this functionObject is saved in the solution
50 functionObjectLibs ("libfieldFunctionObjects.so");
directories (1, 2, 3, and so on). You can visualize this
51
52
enabled
log
true;
true; output using paraview/paraFoam. • This functionObject is used to computed the mass flow across a boundary patch.
53
54 }
writeControl outputTime;
• 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.
543 544

On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects


Final remarks on functionObjects Running functionObjects a-posteriori
• Sometimes it can happen that you forget to use a functionObject or you want to execute a
• As you can see, there are many functionObjects implemented in OpenFOAM®.
functionObject a-posteriori (when the simulation is over).
• We just explained the most common functionObjects. • The solution to this problem is to use the solver with the option -postProcess. This will only
• You can use the banana method to know all the options available for each entry, compute the new functionObject, it will not rerun the simulation.
search in the documentation or read the source code located in the directory • For instance, let us say that you forgot to use a given functionObject. Open the dictionary
$FOAM_SRC/functionObjects controlDict, add the new functionObject, and type in the terminal,
• In the supplement slides you will find more examples of more complex • $> name_of_the_solver -postProcess –dict dictionary_location
functionObjects.
• You will also find a deck of slides with a detailed explanation of advanced paraview • You also have the option of adding the new functionObject in an external file. If you chose this
features and some basic instructions for data plotting and analysis using gnuplot. option, do not forget to add the functionOption within the function sub-dictionary block:
• Remember, you can also do the same postprocessing using paraview/paraFoam, but
you will only work on the saved fields. function
{
• A great advice before running your simulation, setup all your functionObjects and //functionObject definitions here
gather as much as possible quantitative data. };

• By proceeding in this way you do not need to rerun the simulation, you just compute the new
functionObject.
545 546
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
Running functionObjects a-posteriori Exercises
• In the directory system, you will find the following functionObjects external • Where is located the source code of the functionObjects?
dictionaries: functionObject1, functionObject2 and functionObject3 • Try to run in parallel? Do all functionObjects work properly?
• Compute the Courant number using functionObjects.
• Try to figure out what we are doing in every functionObject external dictionary. • Compute the total pressure and velocity gradient using functionObjects (on-the-fly and a-posteriori).
• At this point, let us run each the functionObject a-posteriori. In the terminal type: • Sample data (points, lines and surfaces) using functionObjects (a-posteriori).
• Is it possible to do system calls using functionObjects? If so what functionObject will you use and how do
you use it? Setup a sample case.
1. $> simpleFoam -postProcess -dict system/functionObject1 –noZero • Is it possible to update dictionaries using functionObjects? If so what functionObjects will you use and how
do you use it? Setup a sample case.
2. $> simpleFoam -postProcess -dict system/functionObject2 –time 500:2000
• What are the compulsory entries of the functionObjects?
3. $> simpleFoam -postProcess -dict system/functionObject3 –latestTime

• In step 1, we are reading the dictionary functionObject1 and we are doing the
computation for all the saved solutions, except time zero.
• In step 2, we are reading the dictionary functionObject2 and we are doing the
computation for the time range 500 to 2000
• In step 3, we are reading the dictionary functionObject3 and we are doing the
computation only for he latest save solution.
547 548

Roadmap 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
1. On-the-fly postprocessing – functionObjects and the probes).
postProcess utility
• During the sampling, and inside the case directory, a new directory named
2. Sampling with the postProcess utility 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
3. Field manipulation probesDict.
4. Data conversion • 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.
549 550
Sampling with the postProcess utility Sampling with the postProcess utility
• To do sampling, we will use the solution from the previous case. Running the case
• If you do not have the solution, follow the instructions given in the previous slides.
• Let us do the sampling,
• Hereafter, we will sample along a line and in a few probe locations, as illustrated in
the figure below.
1. $> postProcess -func sampleDict -noZero
2. $> postProcess -func probesDict –time 2000

• In step 1, we do some sampling using the dictionary sampleDict. We also do the


sampling for all the saved solutions, except time zero.
• In step 2, we do some sampling using the dictionary probesDict. We also do the
sampling only for time 2000.

551 552

Sampling with the postProcess utility Sampling with the postProcess utility
The sampleDict and probesDict dictionaries The sampleDict dictionary
• These dictionaries are located in the directory system.
17 type sets; Sample sets (points and lines).
• 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 18 libs ("libsampling.so"); Use sampling library

can be set, 22 interpolationScheme cellPoint; Interpolation method at the solution level (location of the
interpolation points).
• The choice of the interpolationScheme. 2
5 setFormat raw;
• The format of the line data output. 27 surfaceFormat raw;
Format of the output file, raw format is a generic format that can be
read by many applications. The file is human readable (ascii
• The format of the surface data output. 30 fields
format).
31 (
• The fields to be sample. 32
33
U
wallShearStress
Fields to sample. No need to mention that they must exist.

• The sub-dictionaries that controls each sampling operation. 34 );

36 sets Sub-dictionary where we define all sampling objects (sets)


• In these sub-dictionaries you can set the name, type and geometrical 37 (

information of the sampling operation. 39


40
profile0
{
Name of the set and output file

• In this case, the probesDict is used to sample in a set of points. This file contains 42 type lineCellFace; Interpolation method (from the solution to the line).
several entries to be set according to the user needs. The following entries, 44 axis distance;
Sample method definition
• The fields to be sample. 46 start ( 0.75150 0.04767 0 );
47 end ( 0.76168 0.14715 0 ); Location of the sample line. Definition if the start and end point
• Location of the probes.
48 }
• The following functionObjects type can be used to do sampling: patchProbes,
probes, sets, or surfaces. Note:
66 );
553 Use the banana method to know all the options available. 554
Sampling with the postProcess utility Sampling with the postProcess utility
The sampleDict dictionary The probesDict dictionary

17 type sets; • Remember, the sampled data is always saved in the 17 type probes; Sample points.
directory postprocessing
18 libs ("libsampling.so");
• Then, in the sub-directory sampleDict (whose name
22 interpolationScheme cellPoint;
corresponds to the name of the input file), you will find the 20 (
data sampled in a directory corresponding to the sampled 21 p
Fields to sample. No need to mention that they must exist.
2 22 U
5 setFormat raw; time. 23 );

27 surfaceFormat raw; • For example, in this case you fill find the data in the
30 fields directory postProcessing/sampleDict/2000
31 (
32 U • Then, in the file profile0_U_wallShearStress.xy 27 probeLocations
33 wallShearStress 28 (
34 ); you will find the data. 29 (1.0 0 0)
30 (1.25 0 0)
36
37
sets
(
• The name of the output file corresponds to the name of the 31
32
(1.5 0 0)
(1.75 0 0)
sampled set, appended by the name of the sampled fields. 33 (2.0 0 0) Location of the points.
39 profile0
Name of 34 (2.0 -.25 0)
40 { sampled set • Different files will be created for tensor, vector and scalars 35 (2.0 -.5 0)
36 (2.0 .25 0)
42 type lineCellFace; fields. 37 (2.0 .5 0)
38 );
44 axis distance;
• Feel free to open the output files using your favorite text
editor.
46 start ( 0.75150 0.04767 0 );
47 end ( 0.76168 0.14715 0 );

48 }

Note:
66 );
555 Use the banana method to know all the options available. 556

Sampling with the postProcess utility Sampling with the postProcess utility
The probesDict dictionary The output files – functionObject type sets or surfaces

17 type probes; • Remember, the sampled data is always saved in the • The output format of the point sampling (cloud) is as follows:
directory postprocessing
• Then, in the sub-directory probesDict (whose name
20 (
corresponds to the name of the input file), you will find the Scalars
21 p data sampled in a directory corresponding to the sampled
22 U
23 ); time.
#POINT_COORDINATES (X Y Z) SCALAR_VALUE
• For example, in this case you fill find the data in the 0 0 0.05 13.310995
directory postProcessing/probesDict/2000 0 0 0.1 19.293817
27 probeLocations • Then, inside this directory, you will find several files …
28 (
29 (1.0 0 0) containing the sampled data.
30 (1.25 0 0)
31
32
(1.5 0 0)
(1.75 0 0)
• The name of the output file corresponds to the name of the
33 (2.0 0 0) sampled fields, in this case, U and p.
34 (2.0 -.25 0) Vectors
35
36
(2.0 -.5 0)
(2.0 .25 0)
• Feel free to open the output files using your favorite text
37 (2.0 .5 0) editor.
38 );
#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

557 558
Sampling with the postProcess utility Sampling with the postProcess utility
The output files – functionObject type sets or surfaces The output files – functionObject type sets or surfaces

• The output format of the line sampling is as follows: • The output format of the surface sampling is as follows:

Scalars Scalars

#AXIS_COORDINATE SCALAR_VALUE #POINT_COORDINATES (X Y Z) SCALAR_VALUE


0 18.594038 0 0 0.05 13.310995
0.0015 18.249091 0 0 0.1 19.293817
… …

Vectors Vectors

#AXIS_COORDINATE VECTOR_COMPONENTS (X Y Z) #POINT_COORDINATES (X Y Z) VECTOR_COMPONENTS (X Y Z)


0 0 0 1.6152966 0 0 0.05 0 0 2.807395
0.0015 0 0 1.8067536 0 0 0.1 0 0 2.826176
… …

559 560

Sampling with the postProcess utility Sampling with the postProcess utility
The output files – functionObject type probes The output files – functionObject type probes

• The output format of the probing is as follows: • The output format of the probing is as follows:

Scalars Vectors

# Probe 0 (0 0 0.025) # Probe 0 (0 0 0.025)


# Probe 1 (0 0 0.05) # Probe 1 (0 0 0.05)
# Probe 2 (0 0 0.075) # Probe 2 (0 0 0.075)
# Probe 3 (0 0 0.1) # Probe 3 (0 0 0.1)
# Probe 0 1 2 3 # Probe 0 1 2 3
# Time # Time
0 0 0 0 0 0 (0 0 0) (0 0 0) (0 0 0) (0 0 0)
0.005 19.1928 16.9497 14.2011 11.7580 0.005 (0 0 2.1927) (0 0 2.1927) (0 0 2.1927) (0 0 2.1927)
0.01 16.6152 14.5294 12.1733 10.0789 0.01 (0 0 2.5334) (0 0 2.5334) (0 0 2.5334) (0 0 2.5334)
… …
… …
… …

561 562
Sampling with the postProcess utility Roadmap
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 1. On-the-fly postprocessing – functionObjects and the
parentheses of the vector files. postProcess utility
(Hint: you can use sed within gnuplot)
2. Sampling with the postProcess utility
3. Field manipulation
4. Data conversion

563 564

Field manipulation Field manipulation


• Hereafter we are going to deal with field manipulation • To get a list of what can be computed using the postProcess utility, type in
• Field manipulation means modifying a field variable or deriving a new field the terminal:
variable using the primitive variables computed during the solution stage. • $> postProcess –list
• We will do the post-processing using the command line interface (CLI), or
non-GUI mode. • The utility postProcess can take many options. To get more information
• The utility postProcess can be used as a single application, e.g., on how to use the utility, type in the terminal:
• $> postprocess –func vorticity • $> postProcess –help
• $> simpleFoam -postProcess –help
• Or it can be used with a solver using the option –postprocess, e.g.,
• $> simpleFoam -postprocess –func vorticity • The options of the solver using the –postProcess flag are the same as the
options of the utility postProcess.
• Running the solver with the option –postprocess will only execute the • In the sub-directory $FOAM_UTILITIES/postProcessing/postProcess
post-processing and it will let you access data available on the database for you will find the utility postProcess.
the particular solver (such as physical properties or turbulence model). • In the directory $FOAM_SRC/functionObjects, you will find the source
code of the objects that can be used to compute a new field.
565 566
Field manipulation Field manipulation
After computing the solution, we can compute derived fields (e.g., Mach number, density,
• We will now do some field manipulation using the cylinder case. Courant number, vorticity, and so on), using the primitive fields (U, p, T)
Mach number Total pressure
• For this we will use the supersonic wedge tutorial located in the
directory:

$PTOFC/postprocessing/supersonic_wedge/

Divergence of U Divergence of density gradient (numerical shadowgraph)


• 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.

567 568

Field manipulation Field manipulation


What are we going to do? • After finding the solution, we can compute the new field variables using the
• We will use this case to introduce the postProcess utility for field manipulation. primitive variables computed during the solution stage. In the terminal type:
• 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 1. $> rhoPimpleFoam -postProcess -func MachNo
of the solver.
2. $> rhoPimpleFoam -postProcess -func CourantNo
• To find the numerical solution we will use the solver rhoPimpleFoam.
• rhoPimpleFoam is a transient solver for laminar or turbulent flow of compressible gas. 3. $> rhoPimpleFoam -postProcess -func wallShearStress

4. $> rhoPimpleFoam -postProcess -func 'writeObjects(rho)' -time 0

5. $> rhoPimpleFoam -postProcess -func vorticity


Running the case 6. $> postProcess -func vorticity
• Let us run this case using the automatic script, in the terminal type, $> rhoPimpleFoam -postProcess -dict system/externalFunctionObject -latestTime
7.
1. $> sh run_solver.sh
2. $> paraFoam • If the new field variables require information of the simulation database
(fluxes, turbulence properties, transport properties), you will need to process
as in steps 1-5.
• Fell free to open the file run_solver.sh to know all the steps.
• If the new field variable only requires to use a variable that already exist in
the solution folder, you can proceed as in step 6.
569 570
Field manipulation Field manipulation
• In step 1 we compute the Mach number. To compute this value, the postProcess • After finding the solution, we can compute new field variables using the primitive
utility needs to access the thermophysicalProperties dictionary. variables computed during the solution stage. In the terminal type:
• In step 2 we compute the Courant number. To compute this value, the postProcess $> postProcess -func 'grad(U)'
1.
utility needs to access the face fluxes (phi).
2. $> postProcess -func 'components(U)'
• In step 3 we compute the wall shear stress. To compute this value, the postProcess
3. $> postProcess -func 'mag(U)'
utility needs to access the transport and turbulence properties.
4. $> postProcess -func 'magSqr(U)'
• In step 4 we compute the density (rho) for the initial time (time = 0). To compute this
5. $> postProcess -func 'totalPressureCompressible(rho,U,p)' -noZero
value, the postProcess utility needs to access the simulation database.
6. $> postProcess -func 'div(U)' -time 500:1000
• In steps 5 and 6 we compute the vorticity field, this field is derived from the velocity
7. $> postProcess -func 'mag(grad(U))' -latestTime
field. The postProcess utility does not need to access any particular solver
information. Both options will give the same output.
• In step 7 we use an external file to compute the derived fields. In this case we are • We can also use the utility postProcess to compute the average and integral of a
computing the density gradient (grad(rho)) and the divergence of the density gradient specified field over a patch. In the terminal type:
(div(grad(rho)).
8. $> postProcess -func 'patchAverage(name=inlet,p)' –latestTime
• Remember, in order to compute the derived field div(grad(rho), you need to compute
first grad(rho). 9. $> postProcess -func 'patchAverage(name=outlet,U)' –latestTime
10. $> postProcess -func 'patchIntegrate(name=inlet,p)' –latestTime
11. $> postProcess -func 'patchIntegrate(name=outlet,U)' -latestTime
571 572

Field manipulation Roadmap


• In steps 1-11, all the fields are derived from pre-existing fields. The postProcess utility does
not need to access any particular solver information.
• In step 1 we compute the gradient of the velocity vector U. The field is saved as grad(U).
• In step 2 we compute the components of the velocity vector U. The components are saved as
Ux, Uy and Uz.
• In step 3 we compute the magnitude of the velocity vector U. The output is saved as mag(U).
• In step 4 we compute the magnitude squared of the velocity vector U. The output is saved as 1. On-the-fly postprocessing – functionObjects and the
magSqr(U). postProcess utility
• In step 5 we compute the total pressure. The output is saved as total(p). The option –noZero
means do not compute the value for time zero. 2. Sampling and probing with the postProcess utility
• In step 6 we compute the divergence of the velocity vector U. The output is saved as div(U).
You will need to define how to interpolate div(U) in the fvSchemes dictionary. The option –time 3. Field manipulation
500:1000 means save the values between the given range (500-1000).
4. Data conversion
• In step 7 we compute the magnitude of the gradient of the velocity vector U. The output is
saved as mag(Grad(U)). The option –latestTime will compute the value only for the latest
saved solution.
• In step 8 we compute the average of p over the patch inlet.
• In step 9 we compute the average of U over the patch outlet.
• In step 10 we compute the integral of p over the patch inlet.
• In step 11 we compute the integral of U over the patch outlet.

573 574
Data conversion Data conversion
• OpenFOAM® gives users a lot of flexibility when it comes to scientific visualization. ASCII ↔ Binary conversion
• You are not obliged to use OpenFOAM® visualization tools (paraFoam or paraview).
• Another utility that might come in handy, specially when dealing with
• You can convert the solution obtained with OpenFOAM® to many third-party formats large meshes is foamFormatConvert.
by using OpenFOAM® data conversion utilities. 17
18
application icoFoam; • This utility converts the mesh and field variables into ascii or binary
19 startFrom startTime; format.
• If you are looking for a specific format and it is not supported, you can write your own 20
21 startTime 0; • In order to manually edit the boundary file and the field variables
conversion tool. 22
23 stopAt endTime; dictionaries (initial and boundary conditions), they must be in ascii
24
• In the directory $FOAM_UTILITIES/postprocessing/dataConversion, you will 25 endTime 50; format.
26
find the source code of the following data conversion utilities: 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
• foamDataToFluent • foamToTecplot360 31
32
writeInterval 1; dimension of the files (specially for large meshes).
33 purgeWrite 0;
• The drawback is that the files are not human readable anymore.
• foamToEnsight • foamToTetDualMesh 34
35 writeFormat binary;
36 • To convert ascii files into binary files, just type in the terminal:
• foamToEnsightParts • foamToVTK 37 writePrecision 8;
38 • $> foamFormatConvert
39 writeCompression off;
• foamToGMV • smapToFoam 40
• Remember you will need to set the keyword writeFormat to binary
41 timeFormat general;
42
43 timePrecision 6;
in the controlDict dictionary.
• To get more information on how to use a data conversion utility, you can read the 44
45 runTimeModifiable true; • In the same way, if you want to convert from binary to ascii, set the
source code or type in the terminal: keyword writeFormat to ascii in the controlDict dictionary and
type in the terminal:
• $> name_of_data_conversion_utility -help
• $> foamFormatConvert
575 576

Roadmap

1. Finite Volume Method: A Crash Introduction

Module 6 2.
3.
On the CFL number
Linear solvers in OpenFOAM®
Finite volume method overview 4. Pressure-Velocity coupling in OpenFOAM®
5. Unsteady and steady simulations
6. Understanding residuals
7. Boundary and initial conditions
8. Numerical playground

577 578
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Before continuing, we want to remind you that this a brief introduction to the FVM. • Let us use the general transport equation as the starting point to explain the FVM,
• There is much more under the hood.
• 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
• We want to solve the general transport equation for the transported quantity in a to vary linearly around a point P in space and instant t in time,
given domain, with given boundary conditions BC and initial conditions IC.
• This is a second order equation. 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).
• By the way, 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.
Profile assumptions using Taylor expansions around point P (in space) and point t (in time)

579 580

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Let us divide the solution domain into a finite number of arbitrary control volumes or cells, such as the one • In the FVM, a lot of overhead goes into the data book-keeping of the domain information.
illustrated below.
• We know the following information of every control volume in the domain:
• Inside each control volume the solution is sought.
• The control volume has a volume V and is constructed around point P, which is the
• 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.
centroid of the control volume. Therefore the notation .
• We also know which control volumes are internal and which control volumes lie on the boundaries. • The vector from the centroid P of to the centroid N of is named d.
• In the control volume illustrated, the centroid P and face center f are known. • We also know all neighbors of the control volume .
• We also assume that the values of all variables are computed and stored in the centroid of the control volume • The control volume faces are labeled f, which also denotes the face center.
Vp and that they are represented by a piecewise constant profile (the mean value). This is known as the • The location where the vector d intersects a face is .
collocated arrangement.
• The face area vector point outwards from the control volume, is located at the face
• All the previous approximations are at least second order accurate (the ones in the shaded rectangle).
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.

581 582
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Let us recall the Gauss or Divergence theorem, • Let us use the Gauss theorem to convert the volume integrals into surface integrals,

where is a closed surface bounding the control volume and


represents an infinitesimal surface element with associated normal pointing
outwards of the surface , and

• The Gauss or Divergence theorem simply states


that the outward flux of a vector field through a
closed surface is equal to the volume integral of
the divergence over the region inside the surface.
• This theorem is fundamental in the FVM, it is
used to convert the volume integrals appearing in
the governing equations into surface integrals. • At this point the problem reduces to interpolating somehow the cell centered values
(known quantities) to the face centers.

583 584

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Integrating in space each term of the general transport equation and by using Gauss • Integrating in space each term of the general transport equation and by using Gauss
theorem, yields to the following discrete equations for each term theorem, yields to the following discrete equations for each term

Convective term: Diffusive term:

By using Gauss theorem we convert where we have approximated the integrant By using Gauss theorem we convert where we have approximated the integrant
volume integrals into surface integrals by means of the mid point rule, which is volume integrals into surface integrals by means of the mid point rule, which is
second order accurate second order accurate

Gauss theorem: Gauss theorem:

585 586
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Integrating in space each term of the general transport equation and by using Gauss • Integrating in space each term of the general transport equation and by using Gauss
theorem, yields to the following discrete equations for each term theorem, yields to the following discrete equations for each term

Gradient term: Source term:

where we have approximated the centroid gradients by using the Gauss theorem. This approximation is exact if is either constant or varies linearly within the control
This method is second order accurate volume; otherwise is second order accurate.
Sc is the constant part of the source term and Sp is the non-linear part

Gauss theorem: Gauss theorem:

587 588

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Using the previous equations to evaluate the general transport equation over all the Interpolation of the convective fluxes
control volumes, we obtain the following semi-discrete equation
• By looking the figure below, the face values appearing in the convective flux can be
computed as follows,

where is the convective flux and is the


diffusive flux.

• 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. • 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).
589 590
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes Interpolation of the convective fluxes
• By looking the figure below, the face values appearing in the convective flux can be • By looking the figure below, the face values appearing in the convective flux can be
computed as follows, computed as follows,

• This type of interpolation scheme is known as second order upwind differencing


• This type of interpolation scheme is known as upwind differencing and it is first order (SOU), linear upwind differencing (LUD) or Beam-Warming (BW), and it is second
accurate. order accurate.
• This scheme is bounded (non-oscillatory) and diffusive. • For highly convective flows or in the presence of strong gradients, this scheme is
591 oscillatory (unbounded). 592

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes Interpolation of the convective fluxes – TVD schemes
• To prevent oscillations in the SOU, we add a gradient or slope limiter function . • 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).
• By the way, this problem has an exact solution.

• 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.,

• By adding a well-designed limiter function , we get a high resolution (second


order accurate) and bounded scheme (HR). This is a TVD scheme.
593 594
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – TVD schemes Interpolation of the convective fluxes – TVD schemes
• Qualitative comparison of the upwind, linear upwind, linear, and Minmod TVD • Quantitative comparison of the upwind, linear upwind, linear, and Minmod TVD
schemes schemes

Upwind – 1st order Linear – 2nd order


Very bounded but too Diffusive Very accurate but too oscillatory

Linear Upwind – 2nd order Minmod TVD – 2nd order


Bounded and accurate Bounded and accurate

595 596

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Unstructured meshes Interpolation of the convective fluxes – Unstructured meshes
• In the previous explanation, we assumed a line structure (figure A). That is, the cell centers PP, • A simple way around this problem is to redefine
P, and N are all aligned. higher-order schemes in terms of gradients at the
• In unstructured meshes (or meshes used in industrial cases), most of the times the cell center control volume P.
PP is not aligned with the vector connecting cells P and N (figure B). Therefore, extending the • For example, using the gradient of the cells, we can
previous formulations to these meshes is not very straightforward. compute the face values as follows,
• Higher-order schemes for unstructured meshes are an area of active research and new ideas
continue to emerge.

Upwind →

Central difference →

Second order upwind differencing →

• Notice that in this new formulation the cell PP does not appear any more.
• The problem now turns in the accurate and bounded evaluation of the gradients at the cell and
face centers.
• This can be done using the Gauss method, as previously explained.
597 598
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of convective fluxes in a skew mesh Interpolation of diffusive fluxes in an orthogonal mesh
• In the case of a skew mesh (as the one in the figure), we should introduce a correction in order to maintain • By looking the figure below, the face values • By looking the figure below, the face values
second order accuracy and avoid unboundedness when computing gradients. 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,
• One way of doing this is by using an iterative approach for computing successively better approximations to
the gradients.
• We can do a linear reconstruction of the cell and face gradients using compact stencils as follows.

1.

2.

Correction for
3. + interpolated
face gradient

• This is a central difference approximation of the • This type of approximation is second order accurate
Initial approximations
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
599 600

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Correction of diffusive fluxes in a non-orthogonal mesh Mesh induced errors
• By looking the figures below, the face values appearing in the diffusive flux in a non- • In order to maintain second order accuracy, and to avoid unboundedness, we need to correct
orthogonal mesh ( ) can be computed as follows. non-orthogonality and skewness errors.
• Using the over-relaxed approach, the diffusive fluxes can be corrected as follow, • The ideal case is to have an orthogonal and non skew mesh, but this is the exception rather
than the rule.

Over-relaxed approach

Orthogonal and non skew mesh Non-orthogonal and non skew mesh

601 Orthogonal and skew mesh Non-orthogonal and skew mesh 602
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Temporal discretization Temporal discretization
• Using the previous equations to evaluate the general transport equation over all the • Now, we evaluate in time the semi-discrete general transport equation
control volumes, we obtain the following semi-discrete equation,

where is the convective flux and is the


diffusive flux.
• At this stage, we can use any time discretization scheme, e.g., Crank-Nicolson, euler
• After spatial discretization, we can proceed with the temporal discretization. By implicit, forward euler, backward differencing, adams-bashforth, adams-moulton.
proceeding in this way we are using the Method of Lines (MOL).
• It should be noted that the order of the temporal discretization of the transient term
• The main advantage of the MOL method, is that it allows us to select numerical does not need to be the same as the order of the discretization of the spatial terms.
approximations of different accuracy for the spatial and temporal terms. Each Each term can be treated differently to yield different accuracies. As long as the
term can be treated differently to yield to different accuracies. individual terms are at least second order accurate, the overall accuracy will also be
second order.
603 604

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Linear system solution So, what does OpenFOAM® do?
• After spatial and temporal discretization and by using equation • 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
in every control volume of the domain, a system of linear algebraic equations for • Boundary conditions and initials conditions. This information is contained in the directory 0
the transported quantity is assembled, • 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, etc. This information is
contained in the directories constant and/or system
• 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 and
maximum CFL number). This information is set in the system/controlDict dictionary.
• Additionally, we may set sampling and functionObjects for post-processing. This information is
• This system can be solved by using any iterative or direct method. contained in the specific dictionaries contained in the directory system/
605 606
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Where do we set all the discretization schemes in OpenFOAM®? Time discretization schemes
ddtSchemes • The fvSchemes dictionary contains the information related to • There are many time discretization schemes available in OpenFOAM®.
{ the discretization schemes for the different terms appearing in
}
default backward;
the governing equations. • You will find the source code in the following directory:

gradSchemes
• The discretization schemes can be chosen in a term-by-term • $WM_PROJECT_DIR/src/finiteVolume/finiteVolume/ddtSchemes
{ basis.
default Gauss linear;
grad(p) Gauss linear; • The keyword ddtSchemes refers to the time discretization.
} • These are the time discretization schemes that you will use most of the times:
• The keyword gradSchemes refers to the gradient term
divSchemes discretization. • steadyState: for steady state simulations (implicit/explicit).
{
default none; • The keyword divSchemes refers to the convective terms • Euler: time dependent first order (implicit/explicit), bounded.
div(phi,U) Gauss linear; discretization.
} • backward: time dependent second order (implicit), bounded/unbounded.
• The keyword laplacianSchemes refers to the Laplacian terms
laplacianSchemes • CrankNicolson: time dependent second order (implicit), bounded/unbounded.
{
discretization.
default Gauss linear orthogonal; • The keyword interpolationSchemes refers to the method used
}
to interpolate values from cell centers to face centers. It is • First order methods are bounded and stable, but diffusive.
interpolationSchemes unlikely that you will need to use something different from
{ • Second order methods are accurate, but they might become oscillatory.
linear.
default linear;
• At the end of the day, we always want a second order accurate solution.
} • The keyword snGradSchemes refers to the discretization of
snGradSchemes
the surface normal gradients evaluated at the faces. • If you keep the CFL less than one when using the Euler method, numerical diffusion is not that
{
• Remember, if you want to know the options available for each much (however, we advise you to do your own benchmarking).
default orthogonal;
} keyword you can use the banana method.
607 608

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Time discretization schemes Convective terms discretization schemes
• The Crank-Nicolson method as it is implemented in OpenFOAM®, uses a blending factor. • 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
ddtSchemes
{
default CrankNicolson ; • 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.
• Setting to 0 is equivalent to running a pure Euler scheme (robust but first order accurate). • A good TVD scheme (vanLeer or Minmod): TVD, second order accurate, bounded.

• By setting the blending factor equal to 1 you use a pure Crank-Nicolson (accurate but • limitedLinear: second order accurate, unbounded, but more stable than pure linear.
oscillatory, formally second order accurate). Recommended for LES simulations (kind of similar to the Fromm method).

• 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. • First order methods are bounded and stable but diffusive.
• A blending factor of 0.9 is safe to use for most applications. • Second order methods are accurate, but they might become oscillatory.
• At the end of the day, we always want a second order accurate solution.
609 610
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Convective terms discretization schemes Gradient terms discretization schemes
• When you use linearUpwind for div(phi,U), you need to tell OpenFOAM® how to compute the • There are many gradient discretization schemes available in OpenFOAM®.
velocity gradient or grad(U): • 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:
gradSchemes
• Gauss
{
• leastSquares
grad(U) cellMDLimited Gauss linear 1.0;
}
• To avoid overshoots or undershoots when computing the gradients, you can use gradient
limiters.
divSchemes
{ • Gradient limiters increase the stability of the method but add diffusion due to clipping.
div(phi,U) Gauss linearUpwind grad(U); • 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

• Same applies for every transported quantity (e.g. k, epsilon, omega, T)


• All of the gradient discretization schemes are at least second order accurate.
611 612

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Gradient terms discretization schemes Gradient terms discretization schemes
• These are the gradient limiter schemes available in OpenFOAM®: • The gradient limiter implementation in OpenFOAM®, uses a blending factor .

It can be any method

cellMDLimited Less diffusive


cellLimited Note: for smooth field variation, cell gradSchemes
limiting may provide less numerical {
dissipation on meshes with skewed
faceMDLimited default cellMDLimited Gauss linear ;
cells
faceLimited }
More diffusive

Gradient limiter scheme

• Cell limiters will limit cell-to-cell values.


• Setting to 0 is equivalent to turning off the gradient limiter. You gain accuracy but the solution
• Face limiters will limit face-to-cell values. might become unbounded.
• The multi-directional (dimensional) limiters (cellMDLimited and faceMDLimited), will apply the • By setting the blending factor equal to 1 the limiter is always on. You gain stability but you give
limiter in each face direction separately. up accuracy (due to gradient clipping).
• The standard limiters (cellLimited and faceLimited), will apply the limiter to all components of • If you set the blending factor to 0.5, you get the best of both worlds.
the gradient.
• You can use limiters with all gradient discretization schemes.
• The default method is the Minmod.
613 614
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Laplacian terms discretization schemes Laplacian terms discretization schemes
• There are many Laplacian terms discretization schemes available in OpenFOAM®. • The limited method uses a blending factor .
• You will find the source code in the following directory: Surface normal gradients discretization

• $WM_PROJECT_DIR/src/finiteVolume/finiteVolume/snGradSchemes
Only option
laplacianSchemes
{
• These are the Laplacian terms discretization schemes that you will use most of the times: default Gauss linear limited ;
• orthogonal: mainly limited for hexahedral meshes with no grading (a perfect mesh). }
Second order accurate, bounded on perfect meshes, without non-orthogonal Interpolation method of the diffusion coefficient
corrections.
• corrected: for meshes with grading and non-orthogonality. Second order accurate, • Setting to 1 is equivalent to using the corrected method. You gain accuracy, but the solution might
bounded depending on the quality of the mesh, with non-orthogonal corrections. become unbounded.
• By setting the blending factor equal to 0 is equivalent to using the uncorrected method. You give up accuracy
• limited: for meshes with grading and non-orthogonality. Second order accurate, but gain stability.
bounded depending on the quality of the mesh, with non-orthogonal corrections.
• If you set the blending factor to 0.5, you get the best of both worlds. In this case, the non-orthogonal
• uncorrected: usually used on bad quality meshes with grading and non-orthogonality. contribution does not exceed the orthogonal part. You give up accuracy but gain stability.
Second order accurate, without non-orthogonal corrections. Stable but more diffusive • For meshes with non-orthogonality less than 70, you can set the blending factor to 1.
than the limited and corrected methods. • 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 definitely want to
use that mesh, you can set the blending factor to 0.333, and increase the number of non-orthogonal
corrections.
615 • If you are doing LES or DES simulations, use a blending factor of 1 (this means that you need good meshes). 616

Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Laplacian terms discretization schemes What method should I use?
• The surface normal gradients terms usually use the same method as the one chosen for the ddtSchemes • This setup is recommended for most of
{
Laplacian terms. default CrankNicolson 0;
the cases.
}
• For instance, if you are using the limited 1 method for the Laplacian terms, you can use the gradSchemes • It is equivalent to the default method you will find in
same method for snGradSchemes: { 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.

laplacianSchemes
{
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
default Gauss linear limited 1;
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
snGradSchemes { number less than 2.
default Gauss linear limited 1;
{ } • If during the simulation the turbulence quantities
default limited 1; interpolationSchemes
{
become unbounded, you can safely change the
} default linear; discretization scheme to upwind. After all,
}
snGradSchemes
turbulence is diffusion.
{
default limited 1; • Sometimes using gradient limiters for the pressure
} gradient grad(p) is not a good idea as it adds
diffusion.
617 618
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
A very accurate but oscillatory numerics A very stable but too diffusive numerics
ddtSchemes • If you are looking for more accuracy, you can use ddtSchemes • If you are looking for extra stability, you can use this
{ {
default backward;
this method. default Euler;
method.
} }
gradSchemes • In overall, this setup is second order accurate but gradSchemes • This setup is very stable but too diffusive.
{ oscillatory. {
default Gauss linear; default cellLimited Gauss linear 1; • This setup is first order in space and time.
} • Use this setup with LES simulations or laminar grad(U) cellLimited Gauss linear 1;
divSchemes }
• You can use this setup to start the solution in the
{ flows with no complex physics, and meshes with divSchemes presence of bad quality meshes or strong
default none; overall good quality. {
div(phi,U) Gauss linear; default none;
discontinuities.
div(phi,omega) Gauss limitedlinear 1;
div(phi,k) Gauss limitedLinear 1;
div(phi,U) Gauss upwind;
• Remember, you can start using a first order method
div(phi,omega) Gauss upwind;
div((nuEff*dev(T(grad(U))))) Gauss linear; div(phi,k) Gauss upwind; and then switch to a second order method.
} div((nuEff*dev(T(grad(U))))) Gauss linear;
laplacianSchemes } • Start robustly, end with accuracy.
{ laplacianSchemes
default Gauss linear limited 1; { • If this setup fails, you better check boundary
}
interpolationSchemes
default Gauss linear limited 0.5; conditions, physical properties, under-relaxation
}
{ interpolationSchemes factors, time-step, and so on.
default linear; {
} default linear;
snGradSchemes }
{ snGradSchemes
default limited 1; {
} default limited 0.5;
}

619 620

Roadmap On the CFL number


• First of all, what is the CFL or Courant number?
• In one dimension, the CFL number is defined as,

1. Finite Volume Method: A Crash Introduction


2. On the CFL number
3. Linear solvers in OpenFOAM®
4. Pressure-Velocity coupling in OpenFOAM®
• The CFL number is a measure of how much information ( ) traverses a
5. Unsteady and steady simulations computational grid cell ( ) in a given time-step ( ).

6. Understanding residuals • The CFL number is not a magical number.


• The CFL number is a necessary condition to guarantee the stability of the numerical
7. Boundary and initial conditions scheme.
• But not all numerical schemes have the same stability requirements.
8. Numerical playground
• By doing a linear stability study, we can find the stability requirements of each
numerical scheme (but this is out of the scope of this lecture).
621 622
On the CFL number On the CFL number
• Let us now talk about the CFL number condition. The CFL number condition is the maximum allowable
CFL number a solver can use. The CFL number for dummies
• For the N dimensional case, the CFL number condition becomes,
• I like to see the CFL number as follows,

• CFD solvers can be explicit and implicit. • It is an indication of the amount of information that
• Explicit and implicit solvers have different stability requirements. propagates through one cell (or many cells), in one
• Implicit numerical methods are unconditionally stable. time-step.
• 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. • By the way, and this is extremely important, the CFL condition is a necessary
• When we use implicit solvers, we need to assemble a large system of equations. condition for stability (and hence convergence).
• The memory requirements of implicit methods are much higher than those of explicit methods. • But it is not always sufficient to guarantee stability.
• In OpenFOAM®, most of the solvers are implicit.
• In our personal experience, we have been able to go up to a CFL = 5.0 while maintaining the accuracy and
• Other properties of the discretization schemes that you should observe are:
without increasing too much the computational cost. conservationess, boundedness, transportiveness, and accuracy.
• But as we are often interested in the unsteadiness of the solution, we usually use a CFL number in the order of
1.0 623 624

On the CFL number On the CFL number


How to control the CFL number How to control the CFL number

application pimpleFoam; • You can control the CFL number by changing the mesh cell application pimpleFoam; • The option adjustTimeStep will automatically adjust the time
size or changing the time-step size. step to achieve the maximum desired courant number
startFrom latestTime; startFrom latestTime;
(maxCo) or time-step size (maxDeltaT).
startTime 0; • The time step size is set in the controlDict dictionary. startTime 0;
• When any of these conditions is reached, the solver will stop
stopAt endTime; • The easiest way is by changing the time-step size. stopAt endTime;
scaling the time-step size.
endTime 10;
• If you refine the mesh, and you would like to have the same endTime 10;
• To use these features, you need to turn-on the option
deltaT 0.0001; CFL number as the base mesh, you will need to decrease the deltaT 0.0001;
adjustTimeStep.
writeControl runTime; time-step size. writeControl runTime;
• Remember, the first time-step of the simulation is done using
writeInterval 0.1; • On the other side, if you coarse the mesh and you would like writeInterval 0.1;
the value defined with the keyword deltaT and then it is
purgeWrite 0; to have the same CFL number as the base mesh, you will purgeWrite 0;
automatically scaled (up or down), to achieve the desired
need to increase the time-step size.
writeFormat ascii; writeFormat ascii; maximum values (maxCo and maxDeltaT).
writePrecision 8; • The keyword deltaT controls the time-step size of the writePrecision 8;
• It is recommended to start the simulation with a low time-step
simulation (0.0001 seconds in this generic case).
writeCompression off; writeCompression off;
in order to let the solver scale-up the time-step size.
timeFormat general; • If you use a solver that supports adjustable time-step timeFormat general;
• If you want to change the values on-the-fly, you need to turn-
timePrecision 6;
(adjustTimeStep), you can set the maximum CFL number timePrecision 6;
on the option runTimeModifiable.
and maximum allowable time-step using the keywords
runTimeModifiable yes; runTimeModifiable yes;
maxCo and maxDeltaT, respectively. • The feature adjustTimeStep is only present in the PIMPLE
adjustTimeStep yes; adjustTimeStep yes;
family solvers, but it can be added to any solver by modifying
maxCo 2.0; maxCo 2.0; the source code.
maxDeltaT 0.001; maxDeltaT 0.001;

625 626
On the CFL number Roadmap
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. 1. Finite Volume Method: A Crash Introduction
Courant Number mean: 0.10863988 max: 0.73950028
deltaT = 0.001 Current time-step
Courant number (mean and maximum values) 2. On the CFL number
Time = 30.000289542261612 Simulation time

PIMPLE: iteration 1 One PIMPLE iteration (outer loop), this is equivalent to PISO 3. Linear solvers in OpenFOAM®
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
4. Pressure-Velocity coupling in OpenFOAM®
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
5. Unsteady and steady simulations
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
6. Understanding residuals
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
7. Boundary and initial conditions
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
8. Numerical playground
yPlus yplus output:
patch square y+ : min = 0.44603573, max = 6.3894913, average = 2.6323389
writing field yPlus
627 628

Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®


• After spatial and temporal discretization and by using equation
Linear solvers
solvers • The equation solvers, tolerances, and algorithms are controlled
{ from the sub-dictionary solvers located in the fvSolution
p
{
dictionary file.
solver PCG;
• In the dictionary file fvSolution, and depending on the solver
preconditioner DIC;
tolerance 1e-06; you are using you will find the additional sub-dictionaries PISO,
in every control volume of the domain, a system of linear algebraic equations for relTol 0; PIMPLE, and SIMPLE, which will be described later.
the transported quantity is assembled }
pFinal • In this dictionary is where we are telling OpenFOAM® how to
{ crunch numbers.
$p;
relTol 0; • The solvers sub-dictionary specifies each linear solver that is
} used for each equation being solved.
U
{ • The linear solvers distinguish between symmetric matrices and
solver PBiCGStab;
asymmetric matrices.
preconditioner DILU;
tolerance 1e-08; • If you forget to define a linear-solver or use the wrong one,
relTol 0;
} OpenFOAM® will let you know.
}
• The syntax for each entry within the solvers sub-dictionary uses
PISO
a keyword that is the word relating to the variable being solved
{ in the particular equation and the options related to the linear
nCorrectors 2; solver.
nNonOrthogonalCorrectors 1;
}

• This system can be solved by using any iterative or direct method.


629 630
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
Linear solvers Linear solvers
solvers • In this generic case, to solve the pressure (p) we are using the solvers • The linear solvers are iterative, i.e., they are based on reducing
{ PCG method with the DIC preconditioner, an absolute { the equation residual over a succession of solutions.
p p
tolerance equal to 1e-06 and a relative tolerance relTol equal
{ { • The residual is a measure of the error in the solution so that the
solver PCG; to 0. solver PCG;
preconditioner DIC; preconditioner DIC;
smaller it is, the more accurate the solution.
tolerance 1e-06; • The entry pFinal refers to the final pressure correction (notice tolerance 1e-06;
• More precisely, the residual is evaluated by substituting the
relTol 0; that we are using macro syntax), and we are using a relative relTol 0;
} } current solution into the equation and taking the magnitude of
tolerance relTol equal to 0.
pFinal pFinal the difference between the left- and right-hand sides (L2-norm).
{ • To solve the velocity field (U) we are using the PBiCGStab {
$p; method with the DILU preconditoner, an absolute tolerance $p;
relTol 0; relTol 0;
}
equal to 1e-08 and a relative tolerance relTol equal to 0. }
U U
{
• The linear solvers will iterative until reaching any of the {
solver PBiCGStab; tolerance values set by the user or reaching a maximum value solver PBiCGStab;
• It is also normalized to make it independent of the scale of the
preconditioner DILU; of iterations (optional entry). preconditioner DILU;
tolerance 1e-08; tolerance 1e-08; problem being analyzed.
relTol 0; • FYI, solving for the velocity is relatively inexpensive, whereas relTol 0;
} solving for the pressure is expensive. }
} }
• The pressure equation is particularly important as it governs
PISO mass conservation. PISO
{ {
nCorrectors 2; • If you do not solve the equations accurately enough (tolerance), nCorrectors 2;
nNonOrthogonalCorrectors 1; nNonOrthogonalCorrectors 1;
the physics might be wrong.
} }
• Selection of the tolerance is of paramount importance and it
might be problem dependent.
631 632

Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®


Linear solvers Linear solvers
solvers • Before solving an equation for a particular field, the initial • These are the linear solvers available in OpenFOAM®:
{ residual is evaluated based on the current values of the field.
p • GAMG → Multigrid solver • PCG → Newton-Krylov solver
{ • After each solver iteration the residual is re-evaluated. The • PBiCG → Newton-Krylov solver • smoothSolver → Smooth solver
solver PCG;
preconditioner DIC;
solver stops if either of the following conditions are reached: • PBiCGStab → Newton-Krylov solver • diagonalSolver
tolerance 1e-06;
• The residual falls below the solver tolerance, tolerance.
relTol 0; • You will find the source code of the linear solvers in the following directory:
} • The ratio of current to initial residuals falls below the solver • $WM_PROJECT_DIR/src/OpenFOAM/matrices/lduMatrix/solvers
pFinal
{ relative tolerance, relTol.
• When using Newton-Krylov solvers, you need to define preconditoners.
$p; • The number of iterations exceeds a maximum number of • These are the preconditioners available in OpenFOAM®:
relTol 0;
}
iterations, maxIter.
U • DIC • FDIC • diagonal
• The solver tolerance should represent the level at which the
{ • DILU • GAMG • noPreconditioner
solver PBiCG; residual is small enough that the solution can be deemed
preconditioner DILU; sufficiently accurate. • You will find the source code in the following directory:
tolerance 1e-08;
relTol 0; • The keyword maxIter is optional and the default value is 1000. • $WM_PROJECT_DIR/src/OpenFOAM/matrices/lduMatrix/preconditioners
minIter 3;
maxIter 100; • The user can also define the minimum number of iterations • The smoothSolver solver requires the specification of a smoother.
} using the keyword minIter. This keyword is optional, and the • These are the smoothers available in OpenFOAM®:
}
default value is 0.
• DIC • DILUGaussSeidel • nonBlockingGaussSeidel
PISO • DICGaussSeidel • FDIC • symGaussSeidel
{
nCorrectors 2; • DILU • GaussSeidel
nNonOrthogonalCorrectors 1;
} • You will find the source code in the following directory:
633 • $WM_PROJECT_DIR/src/OpenFOAM/matrices/lduMatrix/smoothers 634
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
Linear solvers – General remarks Linear solvers – General remarks
• As you can see, when it comes to linear solvers there are many options and combinations available in • A few comments on the linear solvers residuals (we will talk about monitoring the
OpenFOAM®.
residuals later on).
• When it comes to choosing the linear solver, there is no written theory.
• It is problem and hardware dependent (type of the mesh, physics involved, processor cache memory, network • Residuals are not a direct indication that you are converging to the right solution.
connectivity, partitioning method, and so on).
• Most of the times using the GAMG method (geometric-algebraic multi-grid), is the best choice for symmetric
• The first time-steps the solution might not converge, this is acceptable.
matrices (e.g., pressure). • Also, you might need to use a smaller time-step during the first iterations to
• The GAMG method should converge fast (less than 20 iterations). If it’s taking more iterations, try to change the maintain solver stability.
smoother.
• And if it is taking too long or it is unstable, use the PCG solver. • If the solution is not converging, try to reduce the time-step size.
• When running with many cores (more than 1000), using the PCG might be a better choice.
• For asymmetric matrices, the PBiCGStab method with DILU preconditioner is a good choice.
Time = 50
• The smoothSolver solver with smoother GaussSeidel, also performs very well.
Courant Number mean: 0.044365026 max: 0.16800273
• If the PBiCGStab method with DILU preconditioner mysteriously crashed with an error related to the smoothSolver: Solving for Ux, Initial residual = 1.0907508e-09, Final residual = 1.0907508e-09, No Iterations 0
smoothSolver: Solving for Uy, Initial residual = 1.4677462e-09, Final residual = 1.4677462e-09, No Iterations 0
preconditioner, use the smoothSolver or change the preconditioner. 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
• But in general the PBiCGStab solver should be faster than the smoothSolver solver. ExecutionTime = 4.47 s ClockTime = 5 s
• Remember, asymmetric matrices are assembled from the velocity (U), and the transported quantities (k, fieldMinMax minmaxdomain output:
omega, epsilon, T, and so on). min(p) = -0.37208345 at location (0.025 0.975 0.5)
max(p) = 0.77640927 at location (0.975 0.975 0.5)
• Usually, computing the velocity and the transported quantities is inexpensive and fast, so it is a good idea to use min(U) = (0.00028445255 -0.00028138799 0) at location (0.025 0.025 0.5)
max(U) = (0.00028445255 -0.00028138799 0) at location (0.025 0.025 0.5)
a tight tolerance (1e-8) for these fields. Residuals
• The diagonal solver is used for back-substitution, for instance, when computing density using the equation of
state (we know p and T). 635 636

Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®


Linear solvers Linear solvers
• So how do we set the tolerances? • For the velocity field (U) and the transported quantities (asymmetric matrices), you
• The pressure equation is particularly important, so we should resolve it accurately. can use the following criterion.
Solving the pressure equation is the expensive part of the whole iterative process. • Solving for these variables is relatively inexpensive, so you can start right away with a
• For the pressure equation (symmetric matrix), you can start the simulation with a tight tolerance
tolerance equal to 1e-6 and relTol equal to 0.01. After a while you change these
values to 1e-6 and 0.0, respectively.
Loose tolerance Tight tolerance
• 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.
U U
{ {
Loose tolerance Tight tolerance solver PBiCGStab; solver PBiCGStab;
preconditioner DILU; preconditioner DILU;
tolerance 1e-8; tolerance 1e-8;
relTol 0.001; relTol 0.0;
p p } }
{ {
solver PCG; solver PCG;
preconditioner DIC; preconditioner DIC;
tolerance 1e-6; tolerance 1e-6;
relTol 0.01; relTol 0.0;
} }

637 638
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
Linear solvers Linear solvers
• It is also a good idea to set the minimum number of iterations (minIter), we • When you use the PISO or PIMPLE method, you also have the option to set the
recommend using a value of 3. tolerance for the final pressure corrector step (pFinal).
• If your solver is doing too many iterations, you can set the maximum number of • By proceeding in this way, you can put all the computational effort only in the last
iterations (maxIter). corrector step (pFinal).
• But be careful, if the solver reach the maximum number of iterations it will stop, we • For all the intermediate corrector steps, you can use a more relaxed convergence
are talking about unconverged time-steps or outer-iterations. criterion.
• Setting the maximum number of iterations is especially useful during the first time- • For example, you can use the following solver and tolerance criterion for all the
steps where the linear solver takes longer to converge. intermediate corrector steps (p), then in the final corrector step (pFinal) you tight the
• You can set minIter and maxIter in all symmetric and asymmetric linear solvers. solver tolerance.

Loose tolerance for p Tight tolerance for pFinal


p
{
solver PCG; p pFinal
preconditioner DIC; { {
tolerance 1e-6; solver PCG; solver PCG;
relTol 0.01; preconditioner DIC; preconditioner DIC;
tolerance 1e-4; tolerance 1e-6;
minIter 3;
relTol 0.05; relTol 0.0;
maxIter 100; } }
}
639 640

Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®


Linear solvers Linear solvers
• As we are solving a sparse matrix, the more diagonal the matrix is, the best the convergence rate will be.
• When you use the PISO or PIMPLE method, you also have the option to set the
tolerance for the final pressure corrector step (pFinal). • So it is highly advisable to use the utility renumberMesh before running the simulation.
• $> renumberMesh –overwrite
• By proceeding in this way, you can put all the computational effort only in the last
corrector step (pFinal in this case). • The utility renumberMesh can dramatically increase the speed of the linear solvers, specially during the first
iterations.
• For all the intermediate corrector steps (p), you can use a more relaxed convergence • You will find the source code and the master dictionary in the following directory:
criterion. • $WM_PROJECT_DIR/applications/utilities/mesh/manipulation/renumberMesh
• If you proceed in this way, it is recommended to do at least 2 corrector steps • The idea behind reordering is to make the matrix more diagonally dominant, therefore, speeding up the
(nCorrectors). iterative solver.

Courant Number mean: 0.10556573 max: 0.65793603


deltaT = 0.00097959184
Time = 10

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
Matrix structure plot before reordering Matrix structure plot after reordering
nCorrectors 641 Note: this is the actual pressure matrix from an OpenFOAM® model case 642
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
On the multigrid solvers On the multigrid solvers tolerances
• The development of multigrid solvers (GAMG in OpenFOAM®), together with the • If you go for the GAMG linear solver for symmetric matrices (e.g., pressure), the
development of high resolution TVD schemes and parallel computing, are among the following tolerances are acceptable for most of the cases.
most remarkable achievements of the history of CFD.
Loose tolerance for p Tight tolerance for pFinal
• Most of the time using the GAMG linear solver is fine. However, if you see that the
linear solver is taking too long to converge or is converging in more than 100 p pFinal
iterations, it is better to use the PCG linear solver. { {
solver GAMG; solver GAMG;
• Particularly, we have found that the GAMG linear solver in OpenFOAM® does not tolerance 1e-6; tolerance 1e-6;
relTol 0.01; relTol 0;
perform very well when you scale your computations to more than 500 processors. smoother GaussSeidel; smoother GaussSeidel;
nPreSweeps 0; nPreSweeps 0;
• Also, we have found that for some multiphase cases the PCG method outperforms nPostSweeps 2; nPostSweeps 2;
the GAMG. cacheAgglomeration on; cacheAgglomeration on;
agglomerator faceAreaPair; agglomerator faceAreaPair;
• But again, this is problem and hardware dependent. nCellsInCoarsestLevel 100; nCellsInCoarsestLevel 100;
mergeLevels 1; mergeLevels 1;
• As you can see, you need to always monitor your simulations (stick to the screen for minIter 3; minIter 3;
} }
a while). Otherwise, you might end-up using a solver that is performing poorly. And
this translate in increased computational time and costs.
NOTE:
The GAMG parameters are not optimized, that is up to you.
643
Most of the times is safe to use the default parameters. 644

Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®


Linear solvers tolerances – Steady simulations Linear solvers benchmarking of a model case
• The previous tolerances are fine for unsteady solver.
Case Linear solver for P Preconditioner or smoother MR Time QOI
• For extremely coupled problems you might need to have tighter tolerances.
IC1 PCG FDIC NO 278 2.8265539
• You can use the same tolerances for steady solvers. However, it is acceptable to use
IC2 smoothSolver symGaussSeidel NO 2070 2.8271198
a looser criterion.
IC3 ICCG GAMG NO 255 2.8265538
• You can also set the convergence controls based on residuals of fields. The controls
are specified in the residualControls sub-dictionary of the dictionary file IC4 GAMG GaussSeidel NO 1471 2.8265538
fvSolution. IC5 PCG GAMG-GaussSeidel NO 302 2.8265538

IC6 GAMG GaussSeidel YES 438 2.8265539


SIMPLE
{ IC7 PCG FDIC YES 213 2.8265535
nNonOrthogonalCorrectors 2;
IC8 PCG GAMG-GaussSeidel YES 283 2.8265538

residualControl IC9 ICCG GAMG YES 261 2.8265538


{
p 1e-4; IC10 PCG DIC NO 244 2.8265539
Residual control for every
U 1e-4; field variable you are solving
}
Solver used = icoFoam – Incompressible case
} MR = matrix reordering (renumberMesh)
QOI = quantity of interest. In this case the maximum velocity at the outlet (m/s)
645 TIME = clock time (seconds) 646
Linear solvers in OpenFOAM® Roadmap
Exercises
• Choose any tutorial or a case of your own and do a benchmarking of the linear solvers.
• Using your benchmarking case, find the optimal parameters for the GAMG solver.
• Use different linear solvers for p and pFinal (symmetric matrices). Do you see any advantage? 1. Finite Volume Method: A Crash Introduction
• Do a benchmarking of the different reordering methods available
(Hint: look for the dictionary renumberMeshDict) 2. On the CFL number
• Compare the performance of the asymmetric solvers PBiCG, PBiCGStab, and smoothSolver. Do you see
any significant difference between both solvers?
• Is it possible to switch between segregated and coupled linear solvers on-the-fly?
3. Linear solvers in OpenFOAM®
• In what files are located the controls of the SIMPLE, PISO, and PIMPLE methods?
(Hint: for example, using grep look for the keyword nCorrectors in the directory src/finiteVolume)
4. Pressure-Velocity coupling in OpenFOAM®
5. Unsteady and steady simulations
6. Understanding residuals
7. Boundary and initial conditions
8. Numerical playground

647 648

Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®


• To solve the Navier-Stokes equations we need to use a solution • Many numerical methods exist to solve the Navier-Stokes equations, just to name a few:
• Pressure-correction methods (Predictor-Corrector type).
approach able to deal with the nonlinearities of the governing
• SIMPLE, SIMPLEC, SIMPLER, PISO.
equations and with the coupled set of equations.
• 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.
• 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.
Additional equations deriving from models, such as, volume fraction,
• However, both methods have been extended and reformulated to solve and operate for a wide
chemical reactions, turbulence modeling, combustion, multi-species, etc.
range of flow conditions beyond their original intent.

649
• In OpenFOAM®, you will find segregated pressure-based solvers. 650
Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®
• In OpenFOAM®, you will find segregated pressure-based solvers.
• The following methods are available:
On the origins of the methods
• SIMPLE (Semi-Implicit Method for Pressure-Linked Equations) • SIMPLE
• SIMPLEC (SIMPLE Corrected/Consistent) • S. V. Patankar and D. B. Spalding, “A calculation procedure for heat, mass and
• PISO (Pressure Implicit with Splitting Operators) momentum transfer in three-dimensional parabolic flows”, Int. J. Heat Mass Transfer,
• You will find the solvers in the following directory: 15, 1787-1806 (1972).

• $WM_PROJECT_DIR/applications/solvers • SIMPLE-C
• Additionally, you will find something called PIMPLE, which is an hybrid between SIMPLE and • J. P. Van Doormaal and G. D. Raithby, “Enhancements of the SIMPLE method for
PISO. This method is formulated for very large time-steps and pseudo-transient simulations. predicting incompressible fluid flows”, Numer. Heat Transfer, 7, 147-163 (1984).
• In OpenFOAM®, the PISO and PIMPLE methods are formulated for unsteady simulations.
• PISO
• Whereas, the SIMPLE and SIMPLEC methods are formulated for steady simulations.
• R. I. Issa, “Solution of the implicitly discretized fluid flow equations by operator-
• If conserving time is not a priority, you can use the PIMPLE method for pseudo transient splitting”, J. Comput. Phys., 62, 40-65 (1985).
simulations.
• The pseudo transient PIMPLE method is more stable than the SIMPLE method, but it has a • PIMPLE
higher computational cost. • Unknown origins.
• Depending on the method and solver you are using, you will need to define a specific sub- • Useful reference:
dictionary in the dictionary file fvSolution. • I. E. Barton, “Comparison of SIMPLE and PISO-type algorithms for transient flows, Int.
• For instance, if you are using the PISO method, you will need to specify the PISO sub- J. Numerical methods in fluids, 26,459-483 (1998).
dictionary.
• And depending on the method, each sub-dictionary will have different entries.
651 652

Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®


Pressure-velocity coupling using Pressure-velocity coupling using
the SIMPLE method the PISO method The SIMPLE sub-dictionary
Initial guess p*, u*, v*, w*
• This sub-dictionary is located in the dictionary file fvSolution.
Initial guess p*, u*, v*, w*
• It controls the options related to the SIMPLE pressure-velocity coupling method.
Compute intermediate velocities
(divergent free)
u*, v*, w*
• The SIMPLE method only makes 1 correction.
Compute intermediate velocities
(divergent free)
• An additional correction to account for mesh non-orthogonality is available when using the
u*, v*, w*
SIMPLE method. The number of non-orthogonal correctors is specified by the
Solve Poisson equation for the
pressure correction p'
nNonOrthogonalCorrectors keyword.
Solve Poisson equation for the
• The number of non-orthogonal correctors is chosen according to the mesh quality. For orthogonal
pressure correction p' p* = p Correct pressure and velocities
u* = u
v* = v
p** = p* + p'
u** = u* + u'
meshes you can use 0, whereas, for non-orthogonal meshes it is recommended to do at least 1
w* = w v** = v* + v'

p* = p
w** = w* + w'
correction.
u* = u
v* = v
w* = w
Correct pressure and velocities • However, it is strongly recommended to do at least 1 non-orthogonal correction.
p = p* + p'
Solve second pressure correction
u = u* + u' equation p''
v = v* + v'
w = w* + w'

Correct pressure and velocities


p*** = p** + p''
u*** = u** + u''
v*** = v** + v''
w*** = w** + w'' SIMPLE
Solve additional transport equations
p = p***
u = u***
{
v = v***
w = w***
nNonOrthogonalCorrectors 1;
Solve additional transport equations }
No Yes
Check convergence STOP

No Yes
Check convergence STOP
653 654
Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®
The SIMPLE sub-dictionary The SIMPLE sub-dictionary
• You can use the optional keyword consistent to enable or disable the SIMPLEC method. • Typical under-relaxation factors for the SIMPLE and SIMPLEC methods.
• This option is disable by default. • Remember the under-relaxation factors are problem dependent.
• In the SIMPLEC method, the cost per iteration is marginally higher but the convergence rate is
better so the number of iterations can be reduced. SIMPLE SIMPLEC
• The SIMPLEC method relaxes the pressure in a consistent manner and additional relaxation of
relaxationFactors relaxationFactors
the pressure is not generally necessary.
{ {
• In addition, convergence of the p-U system is better and still is reliable with less aggressive fields equations
relaxation of the momentum equation. { {
p 0.3; U 0.9;
} k 0.9;
equations omega 0.9;
SIMPLE
{ }
{
U 0.7; }
consistent yes;
k 0.7;
nNonOrthogonalCorrectors 1;
omega 0.7;
}
}
}

655 656

Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®


The SIMPLE sub-dictionary The SIMPLE loop in OpenFOAM®

SIMPLEC
fvVectorMatrix UEqn
• If you are planning to use the SIMPLEC (
fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U)
method, we recommend you using under- relaxationFactors );

relaxation factors a little bit more {


fields solve(UEqn == -fvc::grad(p));
conservative that the commonly
{
recommended values.
p 0.7; fvScalarMatrix pEqn
• If during the simulation you still have some }
(
fvm::laplacian(rAU, p) == fvc::div(phiHbyA)
stability problems, try to reduce all the values equations );

to 0.5. {
p 0.7;
• Remember the under-relaxation factors are U = HbyA – rAU*fvc::grad(p);
U 0.7;
problem dependent.
k 0.7;
• For complex physics, it is recommended to omega 0.7;
start the simulation with low values (about }
0.3), and then increase the values slowly up }
to 0.7.
657 658
Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®
The PISO sub-dictionary The PISO sub-dictionary
• This sub-dictionary is located in the dictionary file fvSolution. • You can use the optional keyword momentumPredictor to enable or disable the momentum
• It controls the options related to the PISO pressure-velocity coupling method. predictor step.
• The PISO method requires at least one correction (nCorrectors). To improve accuracy and • The momentum predictor helps in stabilizing the solution as we are computing better
stability you can increase the number of corrections. approximations for the velocity.
• For good accuracy and stability, it is recommended to use 2 nCorrectors. • It is clear that this will add an extra computational cost, which is negligible.
• An additional correction to account for mesh non-orthogonality is available when using the PISO
• In most of the solvers, this option is enabled by default.
method. The number of non-orthogonal correctors is specified by the
nNonOrthogonalCorrectors keyword. • It is recommended to use this option for highly convective flows (high Reynolds number). If you
• The number of non-orthogonal correctors is chosen according to the mesh quality. For orthogonal are working with low Reynolds flow or creeping flows it is recommended to turn it off.
meshes you can use 0, whereas, for non-orthogonal meshes it is recommended to do at least 1 • When you enable the option momentumPredictor, you will need to define the linear solvers for
correction. the variables .*Final (we are using regex notation).
• However, it is strongly recommended to do are least 1 non-orthogonal correction.

PISO
PISO
{
{
momentumPredictor yes;
nCorrectors 2;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
nNonOrthogonalCorrectors 1;
}
}
659 660

Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®


The PISO loop in OpenFOAM® The PIMPLE sub-dictionary
• This sub-dictionary is located in the dictionary file fvSolution.
• It controls the options related to the PIMPLE pressure-velocity coupling method.
fvVectorMatrix UEqn
( • The PIMPLE method works very similar to the PISO method. In fact, setting the keyword
fvm::ddt(U) + fvm::div(phi, U) - fvm::laplacian(nu, U)
);
nOuterCorrectors to 1 is equivalent to running using the PISO method.
• The keyword nOuterCorrectors controls a loop outside the PISO loop.
solve(UEqn == -fvc::grad(p)); • To gain more stability, especially when using large time-steps, you can use more outer correctors
(nOuterCorrectors). Have in mind that this will highly increase the computational cost.
fvScalarMatrix pEqn
(
• Also, if you use under-relaxation factors with more than one nOuterCorrectors, your solution is
fvm::laplacian(rAU, p) == fvc::div(phiHbyA) not anymore time accurate. You are working in pseudo-transient simulations mode.
);

PIMPLE
U = HbyA – rAU*fvc::grad(p); {
momentumPredictor yes;
nOuterCorrectors 1;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
661 662
Roadmap 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).
1. Finite Volume Method: A Crash Introduction • Unsteadiness can be due to:
• Instabilities.
2. On the CFL number • Non-equilibrium initial conditions.
• Time-dependent boundary conditions. Multiphase flow
3. Linear solvers in OpenFOAM® • Source terms. www.wolfdynamics.com/wiki/FVM_uns/ani3.gif

• Chemical reactions and finite rate chemistry.


4. Pressure-Velocity coupling in OpenFOAM® • Phase change.
• Moving or deforming bodies.
5. Unsteady and steady simulations • Turbulence.
6. Understanding residuals • Buoyancy and heat transfer.
• Discontinuities.
Turbulent flows - SRS
7. Boundary and initial conditions • Multiple phases. www.wolfdynamics.com/wiki/FVM_uns/ani4.gif

• Fluid structure interaction.


8. Numerical playground • Combustion.
• And much more.

663 664

Unsteady and steady simulations Unsteady and steady simulations


How to run unsteady simulations in OpenFOAM®? 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 ddtSchemes • The fvSchemes dictionary contains the information related to
and maintains solver stability. { time discretization and spatial discretization schemes.
default backward;
• Select the temporal discretization scheme. } • In this generic case we are using the backward method for time
• Set the tolerance (absolute and/or relative) of the linear solvers. gradSchemes
discretization (ddtSchemes).
{
• Monitor the CFL number. default Gauss linear;
• This scheme is second order accurate but oscillatory.

• Monitor the stability and boundedness of the solution.


grad(p) Gauss linear;
• The parameters can be changed on-the-fly.
}

• Monitor a quantity of interest. divSchemes


{
• And of course, you need to save the solution with a given frequency. default none;
div(phi,U) Gauss linear;
• Have in mind that unsteady simulations generate a lot of data. }
• End time of the simulation?, it is up to you. laplacianSchemes
• In the controlDict dictionary you need to set runtime parameters and general instructions on how to run the {
default Gauss linear orthogonal;
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. interpolationSchemes
{
• In the fvSolution dictionary you need to set the linear solvers. default linear;
}
• 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. snGradSchemes
{
• Additionally, you may set functionObjects in the controlDict dictionary. The functionObjects are used to default orthogonal;
do sampling, probing and co-processing while the simulation is running. }
665 666
Unsteady and steady simulations Unsteady and steady simulations
How to run unsteady simulations in OpenFOAM®? How to run unsteady simulations in OpenFOAM®?
startFrom latestTime; • The controlDict dictionary contains runtime simulation startFrom latestTime; • In this generic case, the solver supports adjustable time-step
controls, such as, start time, end time, time step, saving (adjustTimeStep).
startTime 0; startTime 0;
frequency and so on. Most of the entries are self-explanatory.
• The option adjustTimeStep will automatically adjust the time
stopAt endTime; stopAt endTime;
• This generic case starts from time 0 (startTime), and it will run step to achieve the maximum desired courant number (maxCo)
endTime 10; up to 10 seconds (endTime). endTime 10; or time-step size (maxDeltaT).
deltaT 0.0001; • It will write the solution every 0.1 seconds (writeInterval) of deltaT 0.0001; • When any of these conditions is reached, the solver will stop
simulation time (runTime). scaling the time-step size.
writeControl runTime; writeControl runTime;
• The time step of the simulation is 0.0001 seconds (deltaT). • Remember, the first time-step of the simulation is done using the
writeInterval 0.1; writeInterval 0.1; value defined with the keyword deltaT and then it is
• It will keep all the solution directories (purgeWrite).
purgeWrite 0; purgeWrite 0;
automatically scaled (up or down), to achieve the desired
• It will save the solution in ascii format (writeFormat) with a maximum values (maxCo and maxDeltaT).
writeFormat ascii; precision of 8 digits (writePrecision). writeFormat ascii;
• It is recommended to start the simulation with a low time-step in
writePrecision 8; • And as the option runTimeModifiable is on (yes), we can writePrecision 8; order to let the solver scale-up the time-step size.
modify all these entries while we are running the simulation.
writeCompression off; 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; timeFormat general;
the source code.
timePrecision 6; timePrecision 6;
• If you are planning to use large time steps (CFL much higher
runTimeModifiable yes; runTimeModifiable yes; than 1), it is recommended to do at least 3 correctors steps
(nCorrectors) in PISO/PIMPLE loop.
adjustTimeStep yes; adjustTimeStep yes;
maxCo 2.0; maxCo 2.0;
maxDeltaT 0.001; maxDeltaT 0.001;
667 668

Unsteady and steady simulations Unsteady and steady simulations


How to choose the time-step in unsteady simulations and monitor the solution
How to run unsteady simulations in OpenFOAM®?
• Remember, when running unsteady simulations the time-step must be chosen in such a way
solvers • The fvSolution dictionary contains the instructions of how to
{ that it resolves the time-dependent features and maintains solver stability.
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.
When you use large time steps you do
pFinal
• Depending on the solver you are using, you will need to define not resolve well the physics
{ 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 By using a smaller time step you
PIMPLE at least one correction (nCorrectors). resolve better the physics and you gain
{
stability
nOuterCorrectors 1; • Adding corrections increase the computational cost
nCorrectors 2;
nNonOrthogonalCorrectors 1;
(nOuterCorrectors and nCorrectors).
}
669 670
Unsteady and steady simulations Unsteady and steady simulations
Monitoring unsteady simulations What about steady simulations?
• When running unsteady simulations, it is highly advisable to monitor a quantity of interest.
• First of all, steady simulations are a big simplification of reality.
• The quantity of interest can fluctuate in time, this is an indication of unsteadiness. • Steady simulations is a trick used by CFDers to get fast outcomes with results that might be
even more questionable.
• As mentioned before, most of the flows you will encounter are unsteady.
• In steady simulations we made two assumptions:
• We ignore unsteady fluctuations. That is, we neglect the temporal 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.
• In OpenFOAM® is possible to run steady simulation.
• To do so, you need to use the appropriate solver and use the right discretization scheme.
• As you are not solving the temporal 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).

671 672

Unsteady and steady simulations Unsteady and steady simulations


How to run steady simulations in OpenFOAM®? How to run steady simulations in OpenFOAM®?
• You also need to set the under-relaxation factors (URF).
• In the controlDict dictionary you need to set runtime parameters and • The under-relaxation factors control the change of the variable .
general instructions on how to run the case (such as the number of iterations
to run). You also set the saving frequency.
• Under-relaxation is a feature typical of steady solvers using the SIMPLE family of methods.
• In the fvSchemes dictionary you need to set the temporal discretization • These are the URF commonly used with SIMPLE and SIMPLEC (industry standard),
scheme, for steady simulations it must be steadyState.
• In the fvSolution dictionary you need to set the linear solvers, under- SIMPLE SIMPLEC
relaxation factors and residual controls. p 0.3; p 1; Usually does not require under-relaxing
U 0.7; U 0.9;
• Also, you will need to set the number of corrections of the velocity-pressure k 0.7; k 0.9;
coupling method used (e.g. SIMPLE), this is done in the fvSolution omega 0.7; omega 0.9;
dictionary.
• Additionally, you may set functionObjects in the controlDict dictionary. • 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.
The functionObjects are used to do sampling, probing and co-processing
• Selecting the URF it is kind of equivalent to selecting the right time step
while the simulation is running.
• The URF are bounded between 0 and 1.
• If you set the URF close to one you increase the convergence rate but loose solution stability.
673
• On the other hand, if you set the URF close to zero you gain stability but reduce convergence rate. 674
Unsteady and steady simulations Unsteady and steady simulations
How to run steady simulations in OpenFOAM®? How to run steady simulations in OpenFOAM®?
ddtSchemes • The fvSchemes dictionary contains the information related to startFrom latestTime; • The controlDict dictionary contains runtime simulation
{ time discretization and spatial discretization schemes. controls, such as, start time, end time, time step, saving
default steadyState; startTime 0;
frequency and so on. Most of the entries are self-explanatory.
} • In this generic case and as we are interested in using a steady
stopAt endTime;
gradSchemes
solver, we are using the steadyState method for time • As we are doing a steady simulation, let us talk about iterations
{ discretization (ddtSchemes). endTime 10000; instead of time (seconds).
default Gauss linear;
grad(p) Gauss linear; • It is not a good idea to switch between steady and unsteady deltaT 1; • This generic case starts from iteration 0 (startTime), and it will
} schemes on-the-fly. run up to 10000 iterations (endTime).
writeControl runTime;
divSchemes • For steady state cases, the bounded form can be applied to the • It will write the solution every 100 iterations (writeInterval) of
{ divSchemes, in this case, div(phi,U) bounded Gauss linear. writeInterval 100; simulation time (runTime).
default none;
div(phi,U) bounded Gauss linear; • This adds a linearized, implicit source contribution to the purgeWrite 10; • It will advance the solution one iteration at a time (deltaT).
}
transport equation of the form, writeFormat ascii; • It will keep the last 10 saved solutions (purgeWrite).
laplacianSchemes
{ writePrecision 8; • It will save the solution in ascii format (writeFormat) with a
default Gauss linear orthogonal;
precision of 8 digits (writePrecision).
} writeCompression off;
• And as the option runTimeModifiable is on (true), we can
interpolationSchemes timeFormat general;
{ modify all these entries while we are running the simulation.
default linear; • This term removes a component proportional to the continuity timePrecision 6;
}
error. This acts as a convergence aid to tend towards a bounded runTimeModifiable yes;
snGradSchemes solution as the calculation proceeds.
{
default orthogonal; • At convergence, this term becomes zero and does not
} contribute to the final solution.
675 676

Unsteady and steady simulations Unsteady and steady simulations


How to run steady simulations in OpenFOAM®? How to run steady simulations in OpenFOAM®?
solvers • The fvSolution dictionary contains the instructions of how to • The fvSolution dictionary also contains the
{
solve each discretized linear equation system. relaxationFactors relaxationFactors sub-dictionary.
p {
{ • As for the controlDict and fvSchemes dictionaries, the fields • The relaxationFactors sub-dictionary which controls under-
solver PCG; { relaxation, is a technique used for improving stability when using
preconditioner DIC; parameters can be changed on-the-fly. p 0.3;
tolerance 1e-06; }
steady solvers.
relTol 0; • To set these parameters, follow the guidelines given in the equations
} previous section. {
• Under-relaxation works by limiting the amount which a variable
U 0.7; changes from one iteration to the next, either by modifying the
U
• Increasing the number of nNonOrthogonalCorrectors } solution matrix and source prior to solving for a field (equations
{ corrections will add more stability but at a higher computational }
keyword) or by modifying the field directly (fields keyword).
solver smoothSolver; cost.
smoother symGaussSeidel; • Under-relaxing the equations is also known as implicit under-
tolerance 1e-08; • Remember, nNonOrthogonalCorrectors is used to improve relaxation. Whereas, under-relaxing the fields is also known as
relTol 0; the gradient computation due to mesh quality.
}
explicit under-relaxation.
} • The SIMPLE sub-dictionary also contains convergence controls • An optimum choice of under-relaxation factors is one that is
based on residuals of fields. The controls are specified in the small enough to ensure stable computation but large enough to
SIMPLE
{
residualControls sub-dictionary. move the iterative process forward quickly.
nNonOrthogonalCorrectors 2;
• The user needs to specify a tolerance for one or more solved • In this case we are using the industry standard URF.
residualControl fields and when the residual for every field falls below the
{ corresponding residual, the simulation terminates. • Remember, URF are problem dependent.
p 1e-4;
U 1e-4; • If you do not set the residualControls, the solver will iterate • If you do not define URF, the solver will not under-relax.
} until reaching the maximum number of iterations set in the
}
controlDict dictionary.
677 678
Unsteady and steady simulations Roadmap
Steady simulations vs. Unsteady simulations
• Steady simulations require less computational power than unsteady simulations.
• They are also much faster than unsteady simulations.
• But sometimes they do not converge to the right solution.
1. Finite Volume Method: A Crash Introduction
• They are easier to post-process and analyze (you just need to take a look at the last saved 2. On the CFL number
solution).
• You can use the solution of an unconverged steady simulation as initial conditions for an 3. Linear solvers in OpenFOAM®
unsteady simulation.
• Remember, steady simulations are not time accurate. Therefore is not a good idea to compute 4. Pressure-Velocity coupling in OpenFOAM®
a dominant frequency using steady simulations, e.g., vortex shedding frequency.
5. Unsteady and steady simulations
Steady solution QOI unsteady solution QOI
6. Understanding residuals
7. Boundary and initial conditions
8. Numerical playground

679 680

Understanding residuals Understanding residuals


• This is a typical residual plot for an unsteady simulation. • This is a typical residual plot for a steady simulation.
• Before talking about residuals, let us clarify something.
• Ideally, the solution should converge at every time-step (final • In this case, the initial residuals are falling below the
• When we talk about iterations in unsteady simulations, we are talking about the time- residuals tolerance). convergence criterion (monolithic convergence), hence we
step or outer-iterations. • If the solution is not converging, that is, the residuals are not have reached a steady-state.
reaching the predefined final residual tolerance, try to reduce
• In the solver does not reach the convergence criteria or the
the time-step size.
residuals get stalled, it does not mean that the solution is
• The first time-steps the solution might not converge, this is diverging, it is just an indication of unsteadiness and it
acceptable. might be better to run using an unsteady solver.
• Also, you might need to use a smaller time-step during the
• In comparison to unsteady solvers, steady solvers require
first iterations to maintain solver stability.
less iterations to arrive to a converge solution, if they arrive.
• You can also increase the number of maximum inner
1. To arrive to this physical time of the iterations.
monitored QOI
• If the initial residuals fall bellow the convergence criterion, you
might say that you have arrived to a steady solution (the
exception rather than the rule).

2. We iterate this many times Unsteady solution residuals Steady solution residuals

3. And we iterate inside each time-step (or


outer-iteration), until reaching the linear
solver tolerance or maximum number of
iterations.

681 682
Understanding residuals 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). • This is the output of the residuals for • This is the output of the residuals for
• And by the way, you should get physically realistic values.
all field variables of an unsteady case. all field variables of a steady case.
• In this case, if you monitor the residuals you might get the impression that the simulation is • The jumps are due to the changes in
diverging. tolerance introduced while running
• Instead, if you monitor a QOI you will realize that there is an initial transient (long one by the the simulation.
way), then the onset of an instability, and then a periodic behavior of the phenomenon.
• During the window where the behavior of the QOI is periodic, is where should access the • As you can see, the residuals are
convergence of the solution and compute the unsteady statistics. falling in a monolithic way.
• 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 684

Understanding residuals Roadmap


• This is the output of the aerodynamic • This is the output of the aerodynamic
coefficients for an unsteady case. coefficients for a steady case.

1. Finite Volume Method: A Crash Introduction


2. On the CFL number
3. Linear solvers in OpenFOAM®
4. Pressure-Velocity coupling in OpenFOAM®
5. Unsteady and steady simulations
6. Understanding residuals
7. Boundary and initial conditions
8. Numerical playground

685 686
Boundary conditions and initial conditions Boundary conditions and initial conditions
On the initial boundary value problem (IBVP) A few words about boundary conditions
• Boundary conditions (BC) can be divided into three fundamental mathematical types:
• First of all, when we use a CFD solver to find the approximate solution of the
• Dirichlet boundary conditions: when we use this BC, we prescribe the value of a variable at
governing equations, we are solving an Initial Boundary Value Problem the boundary.
(IBVP). • Neumann boundary conditions: when we use this BC, we prescribe the gradient normal to the
boundary.
• In an IBVP, we need to impose appropriate boundary conditions and initial • Robin Boundary conditions: this BC is a mixed of Dirichlet boundary conditions and Neumann
conditions. boundary
• You can use any of these three boundary conditions in OpenFOAM®.
• No need to say that the boundary conditions and initial conditions need to be • During this discussion, the semantics is not important, that depends of how you want to call the BCs
physically realistic. or how they are named in the solver, i.e., in, inlet, inflow, velocity inlet, incoming flow and so on.
• Defining boundary conditions involves:
• Boundary conditions are a required component of the numerical method,
• Finding the location of the boundary condition in the domain.
they tell the solver what is going on at the boundaries of the domain. • Determining the boundary condition type.
• You can think of boundary conditions as source terms. • Giving the required physical information.
• The choice of the boundary conditions depend on:
• Initial conditions are also a required component of the numerical method, • Geometrical considerations.
they define the initial state of the problem. • Physics involved.
• Information available at the boundary condition location.
• Numerical considerations.
• And most important, you need to understand the physics involved.
687 688

Boundary conditions and initial conditions Boundary conditions and initial conditions
A few words about boundary conditions A few words about initial conditions
• To define boundary conditions you need to know the location of the boundaries (where they are • Initial conditions (IC) can be divided into two groups:
in your mesh). • Uniform initial conditions.
• You also need to supply the information at the boundaries. • Non-uniform initial conditions.
• For non-uniform IC, the value used can be obtained from:
• Last but not least important, you must know the physics involved.
• Another simulation (including a solution with • A mathematical function
different grid resolution).
• A potential solver. • Reduced order models.
• Experimental results.

• Defining initial conditions involves:


• Finding the location of the initial condition in the domain.
• Determining the initial condition type.
• Giving the required physical information.
• The choice of the initial conditions depend on:
• Geometrical considerations.
• Physics involved.
• Information available.
• Numerical considerations.
689 • And most important, you need to understand the physics involved. 690
Boundary conditions and initial conditions Boundary conditions and initial conditions
A few words about initial conditions • Inlets and outlets boundary conditions:

• For initial conditions, you need to supply the initial information or initial state of your problem.
• Inlets are for regions where inflow is expected; however, inlets might support
outflow when a velocity profile is specified.
• This information can be a uniform value or a non-uniform value.
• Pressure boundary conditions do not allow outflow at the inlets.
• You can apply the initial conditions to the whole domain or separated zones of the domain.
• Velocity specified inlets are intended for incompressible flows.
• Last but not least important, you must know the physics involved. • Pressure and mass flow inlets are suitable for compressible and incompressible
flows.
• Same concepts apply to outlets, which are regions where outflow is expected.

691 692

Boundary conditions and initial conditions Boundary conditions and initial conditions
• Zero gradient and backflow boundary conditions: • On the outlet pressure boundary condition
• Zero gradient boundary conditions extrapolates the values from the domain. • Some combinations of boundary conditions are very stable and some are less
They require no information. reliable.
• Zero gradient boundary conditions can be used at inlets, outlets, and walls. • And some configurations are unreliable.
• Inlet velocity at the inlet and pressure zero gradient at the outlet. This
• Backflow boundary conditions provide a generic outflow/inflow condition, with
combination should be avoided because the static pressure level is not
specified inflow/outflow for the case of backflow.
fixed.
• In the case of a backflow outlet, when the flux is positive (out of domain) it • Qualitatively speaking, the results are very different.
applies a Neumann boundary condition (zero gradient), and when the flux is
• This simulation will eventually crash.
negative (into of domain), it applies a Dirichlet boundary condition (fixed value).
• Same concept applies to backflow inlets. BCs 1. Inlet velocity and fixed outlet pressure
www.wolfdynamics.com/wiki/BC/aniBC1.gif
BCs 2. Inlet velocity and zero gradient outlet pressure
www.wolfdynamics.com/wiki/BC/aniBC2.gif

693 694
Boundary conditions and initial conditions Boundary conditions and initial conditions
• On the outlet pressure boundary condition • Symmetry boundary conditions:
• If you only rely on a QOI and the residuals, you will not see any major difference • Symmetry boundary conditions are a big simplification of the problem. However,
between the two cases with different outlet pressure boundary condition. they help to reduce mesh cell count.
• This is very misleading. • Have in mind that symmetry boundary conditions only apply to planar faces.
• However, when you visualize the solution you will realize that something is
• To use symmetry boundary conditions, both the geometry and the flow field must
wrong. This is a case where pretty pictures can be used to troubleshoot the
be symmetric.
solution.
• Quantitative speaking, the results are very similar. • Mathematically speaking, setting a symmetry boundary condition is equivalent
to: zero normal velocity at the symmetry plane, and zero normal gradients of all
• However, this simulation will eventually crash.
variables at the symmetry plane.
• Physically speaking, they are equivalent to slip walls.
Residual plot for pressure Quantity of interest – Force coefficient on the body

695 696

Boundary conditions and initial conditions Boundary conditions and initial conditions
• Location of the outlet boundary condition: • Domain dimensions (when the dimensions are not known):
• Place outlet boundary conditions as far as possible from recirculation zones or • If you do not have any constrain in the domain dimensions, you can use as a general guideline the
dimensions illustrated in the figure, where L is a reference length (in this case, L is the wing chord).
backflow conditions, by doing this you increase the stability.
• Always verify that there are no significant gradients normal to any of the boundaries patches. If there
• Remember, backflow conditions requires special treatment. are, you should consider increasing the domain dimensions.
Far enough so the flow can be
Possible backflow Might be OK
considered fully developed

697 698
Boundary conditions and initial conditions Boundary conditions and initial conditions
A few considerations and guidelines A few considerations and guidelines
• Boundary conditions and initial conditions need to be physically realistic. • Inlets that take flow into the domain from the atmosphere can use a total pressure boundary condition (e.g.
• Poorly defined boundary conditions can have a significant impact on your solution. open window).
• Initial conditions are as important as the boundary conditions. • Mass flow inlets produce a uniform velocity profile at the inlet.
• A good initial condition can improve the stability and convergence rate. • Pressure specified boundary conditions allow a natural velocity profile to develop.
• On the other hand, unphysical initial conditions can slow down the convergence rate or can cause divergence. • The required values of the boundary conditions and initial conditions depend on the equations you are solving
and physical models used, e.g.,
• You need to define boundary conditions and initials conditions for every single variable you are solving.
• For incompressible and laminar flows you will need to set only the velocity and pressure.
• Setting the right boundary conditions is extremely important, but you need to understand the physics.
• If you are solving a turbulent compressible flow you will need to set velocity, pressure, temperature and
• You need to understand the physics in order to set the right boundary conditions.
the turbulent variables.
• Do not force the flow at the outlet, use a zero normal gradient for all flow variables except pressure. The solver
• For multiphase flows you will need to set the primitives variables for each phase. You will also need to
extrapolates the required information from the interior.
initialize the phases.
• Be careful with backward flow at the outlets (flow coming back to the domain) and backward flow at inlets
• If you are doing turbulent combustion or chemical reactions, you will need to define the species, reactions
(reflection waves), they required special treatment.
and turbulent variables.
• If possible, select inflow and outflow boundary conditions such that the flow either goes in or out normal to the
• Minimize grid skewness, non-orthogonality, growth rate, and aspect ratio near the boundaries. You do not want
boundaries.
to introduce diffusion errors early in the simulation, especially close to the inlets.
• At outlets, use zero gradient boundary conditions only with incompressible flows and when you are sure that the
• Try to avoid large gradients in the direction normal to the boundaries and near inlets and outlets. That is to say,
flow is fully developed.
put your boundaries far away from where things are happening.
• 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 700

Boundary conditions and initial conditions Boundary conditions and initial conditions
• OpenFOAM® distinguish between base type boundary conditions and numerical type • The following base type and numerical type boundary conditions are
boundary conditions.
constrained or paired.

Base type boundary conditions Numerical type boundary conditions


• 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).
• Base type boundary conditions are based on • Numerical type boundary condition assigns the
geometry information (surface patches) or on inter- value to the field variables in the given surface
processor communication link (halo boundaries). patch.
• Base type boundary conditions are defined in the • Numerical type boundary conditions are defined in
Base type Numerical type
file boundary located in the directory
the field variables dictionaries located in the
constant/polyMesh directory 0 (e.g. U, p).
• The file boundary is automatically created when
constant/polyMesh/boundary 0/U - 0/p - 0/T - 0/k - 0/omega (IC/BC)
• When we talk about numerical type boundary
you generate or convert the mesh.
conditions, we are referring to Dirichlet, Neumann
• When you convert a mesh to OpenFOAM® format, symmetry symmetry
or Robin boundary conditions.
you might need to manually modify the file symmetryPlane symmetryPlane
• You need to manually create the field variables
boundary. This is because the conversion utilities
dictionaries (e.g. 0/U, 0/p, 0/T, 0/k, 0/omega).
do not recognize the boundary type of the original empty empty
mesh. • Remember, if you forget to define a numerical
boundary condition, OpenFOAM® will complain and wedge wedge
• Remember, if a base type boundary condition is
will tell you where and what is the error.
missing, OpenFOAM® will complain and will tell you cyclic cyclic
where and what is the error. • Also, if you misspelled something OpenFOAM® will
complain and will tell you where and what is the cyclicAMI cyclicAMI
• Also, if you misspelled something OpenFOAM® will
error.
complain and will tell you where and what is the processor processor
error
701 702
Boundary conditions and initial conditions Boundary conditions and initial conditions
• The base type patch can be any of the boundary conditions available in • The wall base type boundary condition is defined as follows:
OpenFOAM®.
• Mathematically speaking; they can be Dirichlet, Neumann or Robin
boundary conditions. Base type Numerical type

constant/polyMesh/boundary 0/U 0/p


Base type Numerical type

constant/polyMesh/boundary 0/U - 0/p (IC/BC) type fixedValue;


wall zeroGradient
value uniform (0 0 0);
fixedValue
zeroGradient
inletOutlet
slip • This boundary condition is not contained in the patch base type boundary conditions
patch
totalPressure group, because specialize modeling options can be used on this boundary condition.
supersonicFreeStream
• An example is turbulence modeling, where turbulence can be generated or
and so on … dissipated at the walls.
Refer to the doxygen documentation for a list of all numerical
boundary conditions available.

703 704

Boundary conditions and initial conditions Boundary conditions and initial conditions
• To deal with backflow at outlets, you can use the following boundary condition: • Typical boundary conditions are as follows (external aerodynamics),

Boundary type description Pressure Velocity Turbulence fields

Base type Numerical type


Inlet zeroGradient fixedValue fixedValue

constant/polyMesh/boundary 0/U 0/p Outlet fixedValue inletOutlet inletOutlet

Wall zeroGradient fixedValue Wall functions*


type inletOutlet;
type fixedValue;
patch inletValue uniform (0 0 0); Symmetry symmetry symmetry symmetry
value uniform 0;
value uniform (0 0 0);

Periodic cyclic cyclic cyclic

Empty face (2D) empty empty empty

• The inletValue keyword is used for the reverse flow. Slip wall slip slip slip
• In this case, if flow is coming back into the domain it will use the value set using the
keyword inletValue. Otherwise it will use a zeroGradient boundary condition.
* Wall functions can be: kqWallFunction, omegaWallFunction, nutkWallFunction, and so on
(next slide).
705 706
Boundary conditions and initial conditions Boundary conditions and initial conditions
• Typical wall functions boundary conditions are as follows, • 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.
Field variable Wall functions – High RE Resolved BL – Low RE
• Pay attention to this, specially if you are converting the mesh from another format.
nut nut(–)WallFunction* fixedValue 0 or a small number
• Also, do not use spaces of funny characters when assigning the names to the
boundary patches.
k, q, R kqRWallFunction fixedValue 0 or a small number
• The following names are consistent among all dictionary files,
zeroGradient or fixedValue 0 or
epsilon epsilonWallFunction
a small number

omegaWallFunction or Base type Numerical type


omega omegaWallFunction
fixedValue with a big number
constant/polyMesh/boundary 0/U 0/p
zeta – fixedValue 0 or a small number

inlet inlet inlet


nuTilda – fixedValue 0 or a small number
top top top
* nutkAtmRoughWallFunction, nutkRoughWallFunction, nutkWallFunction, cylinder cylinder cylinder
nutLowReWallFunction, nutURoughWallFunction, nutUSpaldingWallFunction,
nutUTabulatedWallFunction, nutUWallFunction, nutWallFunction. sym sym sym
707 708

Boundary conditions and initial conditions Boundary conditions and initial conditions
• There are numerous numerical type boundary conditions implemented in The constant/polyMesh/boundary dictionary
OpenFOAM®.
• For a generic case, the file boundary is divided as follows
• You can find the source code of the numerical boundary conditions in the
following directory: 3 Number of surface patches
(
There must be 3 patches definition.
• $WM_PROJECT_DIR/src/finiteVolume/fields movingWall
{
type patch;
inGroups 1(patch); movingWall
nFaces 20;
startFace 760;
} frontAndBack
• The wall boundary conditions for the turbulence models (wall functions), are
fixedWalls
located in the following directory: {
type wall;

• $WM_PROJECT_DIR/src/TurbulenceModels/turbulenceModels inGroups
nFaces
1(wall);
60;

fixedWalls
startFace 780;
/derivedFvPatchFields/wallFunctions

fixedWalls
}

frontAndBack
{
type empty;
inGroups 1(empty);
• To get more information about all the boundary conditions available in nFaces 800;
startFace 840;
OpenFOAM® you can read the Doxygen documentation, just look for the } frontAndBack
)
Using OpenFOAM section at the bottom of the page. You can access the
documentation online, http://cpp.openfoam.org/v5/ fixedWalls

709 710
Boundary conditions and initial conditions Boundary conditions and initial conditions
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary

• For a generic case, the file boundary is divided as follows • For a generic case, the file boundary is divided as follows

3 3
( Name and type of the surface patches ( inGroups keyword
movingWall movingWall
{ {
type patch; • The name and type of the patch is given by type patch; • This is optional.
inGroups 1(patch); inGroups 1(patch);
the user.
nFaces 20; nFaces 20; • You can erase this information safely.
startFace 760; startFace 760;
} • You can change the name if you do not like it. } • It is used to group patches during visualization
Do not use strange symbols or white spaces.
fixedWalls fixedWalls in ParaView/paraFoam. If you open this mesh
{ • You can also change the base type. For { in paraFoam you will see that there are two
type wall; type wall;
inGroups 1(wall); instance, you can change the type of the inGroups 1(wall); groups, namely: wall and empty.
nFaces 60; patch movingWall from patch to wall. nFaces 60;
startFace 780; startFace 780; • As usual, you can change the name.
} • When converting the mesh from a third-party }
• If you want to put a surface patch in two
format, OpenFOAM® will try to recover the
frontAndBack frontAndBack groups, you can proceed as follows:
{ information from the original format. But it {
type empty; might happen that it does not recognize the type empty; 2(wall wall1)
inGroups 1(empty); inGroups 1(empty);
nFaces 800; base type and name of the original format. If nFaces 800; In this case the surface patch belongs to the
startFace 840; that is your case, you will need to modify the startFace 840;
} } group wall (which can have another patch)
file manually.
) ) and wall1

711 712

Boundary conditions and initial conditions Boundary conditions and initial conditions
The constant/polyMesh/boundary dictionary The constant/polyMesh/boundary dictionary

• For a generic case, the file boundary is divided as follows • For a generic case, the file boundary is divided as follows

3 3
Remember
( (
movingWall movingWall
{ { Boundary patches that are not recognize or
type patch; type patch; assigned to a patch are grouped automatically in
inGroups 1(patch); inGroups 1(patch);
nFaces 20; nFaces and startFace keywords nFaces 20;
a default group named defaultFaces of type
startFace 760; startFace 760; empty.
} }
• Unless you know what you are For instance, if a boundary patch does not have a
fixedWalls fixedWalls type and a name, they will be grouped as follows:
{
doing, you do not need to change {
type wall; this information. type wall;
inGroups 1(wall); inGroups 1(wall);
nFaces 60; • Basically, this is telling you the nFaces 60; defaultFaces
startFace 780; startFace 780; {
starting face and ending face of the type empty;
} }
patch. inGroups 1(empty);
frontAndBack frontAndBack nFaces 800;
{ • This is created automatically when { startFace 840;
type empty; type empty; }
generating the mesh or converting
inGroups 1(empty); inGroups 1(empty);
nFaces 800;
the mesh. nFaces 800;
startFace 840; startFace 840;
} }
And as usual, you can manually change the name
) ) and type.

713 714
Boundary conditions and initial conditions Boundary conditions and initial conditions
The 0/U dictionary The 0/p dictionary

• For a generic case, the numerical type BC are assigned as follows (U), • For a generic case, the numerical type BC are assigned as follows (p),
movingWall
dimensions [0 1 -1 0 0 0 0]; type fixedValue; dimensions [0 2 -2 0 0 0 0]; movingWall
value uniform (1 0 0); type zeroGradient;
internalField uniform (0 0 0); internalField uniform 0;

boundaryField frontAndBack boundaryField frontAndBack


{ type empty; { type empty;

value uniform (0 0 0);

type zeroGradient;
movingWall movingWall
{ {

type fixedValue;
type fixedValue; type zeroGradient;

value uniform (0 0 0);


value uniform (1 0 0); }

type zeroGradient;

fixedWalls
}

fixedWalls
fixedWalls

type fixedValue;
fixedWalls {
{ type zeroGradient;

fixedWalls
fixedWalls
type fixedValue; }
value uniform (0 0 0);
} frontAndBack
{
frontAndBack type empty;
{ frontAndBack } frontAndBack
type empty; }
type empty; type empty;
}
}
fixedWalls fixedWalls
type fixedValue; type zeroGradient;
value uniform (0 0 0);

715 716

Roadmap Numerical playground

1. Finite Volume Method: A Crash Introduction Merry-go-round:


2. On the CFL number Pure convection of a passive scalar in a vector
3. Linear solvers in OpenFOAM® field – One dimensional tube.
4. Pressure-Velocity coupling in OpenFOAM®
5. Unsteady and steady simulations
6. Understanding residuals
7. Boundary and initial conditions
8. Numerical playground

717 718
Numerical playground Numerical playground
• This is a visual and mental exercise only. Pure convection of a scalar in a vector field – One dimensional tube.

• You will find this case in the directory

$PTOFC/101FVM/pureConvection

• In this directory, you will also find the README.FIRST file with
the instructions of how to run the case. U = zeroGradient
T = zeroGradient

• Hereafter, we will focus our eyes to train our brain. 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

719 720

Numerical playground Numerical playground


• This problem has an exact solution in the form of a traveling wave.
Comparison of different spatial discretization schemes. Comparison of different spatial discretization schemes.
• We will use this case to study the different discretization schemes implemented in Euler in time – 100 cells – CFL = 0.1 Euler in time – 100 cells – CFL = 0.1
OpenFOAM®. Linear limiter functions on the Sweby diagram. Non-linear limiter functions on the Sweby diagram.

• 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

721 722
Numerical playground Numerical playground
Comparison of different gradient limiters. Comparison of different gradient limiters. Comparison of different temporal discretization Comparison of Crank Nicolson blending factor using
Linear upwind in space – Euler in time – 100 cells – Linear upwind in space – Euler in time – 100 cells – schemes and gradient limiters. cellLimited leastSquares 0.5 gradient limiter.
CFL 0.1 CFL 0.1 Linear upwind in space – 100 cells – CFL 0.1 Linear upwind in space – 100 cells – CFL 0.1

723 724

Numerical playground Numerical playground


• This case was for your eyes and brain only, but we encourage you to reproduce all
Comparison of different time-step size (different CFL Comparison of different mesh sizes. the previous results,
number). Linear upwind in space – Euler in time
Linear upwind in space – Euler in time – 100 cells • 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.

• Sample the solution and compare the results.


• Try to find the best combination of numerical schemes.
• Remember, in the README.FIRST file you will find the instructions of
how to run the case.

725 726
Numerical playground Numerical playground
Exercises Exercises
• Which one of the following schemes is useless: • By the way, the solver scalarTransportFoam does not report the CFL number on the screen. How will you
• upwind compute the CFL number in this case?
• downwind (Hint: you can take a look at the post-processing slides or the utilities directory)
• linear • Which one is more diffusive, spatial discretization or time discretization?
• Compare the solution obtained with the following schemes: • Are all time discretization schemes bounded?
• upwind • If you are using the Crank-Nicolson scheme, how will you avoid oscillations?
• linearUpwind • Does the solution improve if you reduce the time-step?
• MUSCL • Use the upwind scheme and a really fine mesh. Do the accuracy of the solution improve?
• QUICK • From a numerical point of view, what is the Peclet number? Can it be compare to the Reynolds number?
• cubic
• UMIST
Are all of them bounded? Are they second order accurate?

• Use the linearUpwind method with Gauss linear and leastSquares for gradient computations, which method
is more accurate? • If the Peclet number is more than 2, what will happen with your solution if you were using a linear scheme?
• Imagine that you are using the linearUpwind method with no gradient limiters. How will you stabilize the (Hint: to change the Peclet number you will need to change the diffusion coefficient)
solution if it becomes unbounded? • Pure convection problems have analytical solutions. You are asked to design your own tutorial with an
• When using gradient limiters, what is clipping? analytical solution in 2D or 3D.
• Use the vanLeer method with a CFL number of 0.1 and a CFL number of 0.9, did both solutions converge? • Try to break the solver using a time step less than 0.005 seconds. You are allow to modify the original mesh
Are both solutions bounded? and use any combination of discretization schemes.

727 728

Numerical playground Numerical playground


• This is a visual and mental exercise only.
• You will find this case in the directory

Slide: $PTOFC/101FVM/laplace
2D Laplace equation in a square domain. • In this directory, you will also find the README.FIRST file with
the instructions of how to run the case.

• Hereafter, we will focus our eyes to train our brain.

729 730
Numerical playground Numerical playground
2D Laplace equation in a square domain 2D Laplace equation in a square domain
• This case consist of one domain and three different element types.

Domain

Detailed section view

731 Hexahedral mesh Triangular mesh Polyhedral mesh 732

Numerical playground Numerical playground


2D Laplace equation in a square domain 2D Laplace equation in a square domain

• We will study the influence of the element type on the gradients computation.
A B
• We will study the influence of the gradSchemes method and laplacianSchemes gradSchemes:
method on the solution. Gauss linear

laplacianSchemes:
Gauss linear orthogonal

A. Hexahedral mesh
B. Triangular mesh
This problem has the following C. Polyhedral mesh
analytical solution:
C

T field
733 734
Numerical playground Numerical playground
2D Laplace equation in a square domain 2D Laplace equation in a square domain

A B gradSchemes:
A B gradSchemes:
Gauss linear Gauss linear

laplacianSchemes: laplacianSchemes:
Gauss linear orthogonal Gauss linear limited 1

A. Hexahedral mesh A. Hexahedral mesh


B. Triangular mesh B. Triangular mesh
C. Polyhedral mesh C. Polyhedral mesh

C C

field field
735 736

Numerical playground Numerical playground


2D Laplace equation in a square domain 2D Laplace equation in a square domain

A B gradSchemes:
A B gradSchemes:
Gauss leastSquares Gauss leastSquares

laplacianSchemes: laplacianSchemes:
Gauss linear orthogonal Gauss linear limited 1

A. Hexahedral mesh A. Hexahedral mesh


B. Triangular mesh B. Triangular mesh
C. Polyhedral mesh C. Polyhedral mesh

C C

field field
737 738
Numerical playground Numerical playground
• This case was for your eyes and brain only, but we encourage you to reproduce all Exercises
the previous results. • Run the case using all gradient discretization schemes available. Which scheme gives the best results?
• In the subdirectory c1 you will find the hexahedral mesh, in the subdirectory c2 you • According to the previous results, which element type is the best one? Do you think that the choice of the
will find the triangular mesh, and in the subdirectory c3 you will find the polyhedral element type is problem dependent (e.g., direction of the flow)?
mesh. • 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?
• Use the script runallcases.sh to run all the cases automatically. (Hint: look at the corrections)
• When launching paraFoam it will give you a warning, accept the default option (yes). • 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
• In paraFoam, go to the File menu and select Load State. Load the state located iterations? Compare the solutions.
in the directory paraview (state1.pvsm). • 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 allow to modify the original mesh and use
• In the window that pops out, give the location of the *.foam files inside each
any combination of discretization schemes.
subdirectory (c1/c1.foam, c2/c2.foam, and c3/c3.foam).
• The file state1.pvsm will load a preconfigured state with all the solutions.
• If you are interested in running the cases individually, enter the subdirectory
and follow the instructions in the README.FIRST file.

739 740

Numerical playground Numerical playground


Flow in a lid-driven square cavity – Re = 100
Non-orthogonal mesh vs. orthogonal mesh

Swing:
Flow in a lid-driven square cavity – Re = 100
Effect of grading and non-orthogonality on the
accuracy of the solution

Non-orthogonal mesh Orthogonal mesh


The overall quality of this mesh is good (in This is a perfect mesh
terms of non-orthogonality and skewness),
but by no standard this is a good mesh.

• We will use this case to learn how to adjust the numerical schemes according to
mesh non-orthogonality and grading.
741 742
Numerical playground Numerical playground
LaplacianSchemes orthogonal – Non-orthogonal corrections disabled LaplacianSchemes orthogonal – Non-orthogonal corrections enabled
Y centerline Y centerline

• And as CFD is not only about pretty colors, we should also And as CFD is not only about pretty colors, we should also
validate the results validate the results
X centerline X centerline

High-Re Solutions for incompressible flow using the navier-stokes equations and a multigrid method High-Re Solutions for incompressible flow using the navier-stokes equations and a multigrid method
U. Ghia, K. N. Ghia, C. T. Shin. U. Ghia, K. N. Ghia, C. T. Shin.
Journal of computational physics, 48, 387-411 (1982) 743 Journal of computational physics, 48, 387-411 (1982) 744

Numerical playground Numerical playground


How to adjust the numerical method to deal with non-orthogonality How to adjust the numerical method to deal with non-orthogonality
17 ddtSchemes • In the dictionary fvSchemes we can enable non- 17 solvers • Additionally, in the dictionary fvSolution we need to
18 { 18 {
19 default backward; orthogonal corrections. 19 p define the number of PISO corrections (nCorrectors) and
20 } 20 { non-orthogonal corrections (nNonOrthogonalCorrectors).
21 • Non-orthogonal corrections are chosen using the 21 solver PCG;
22 gradSchemes 22 preconditioner DIC;
23 { keywords laplacianSchemes and snGradSchemes. 23 tolerance 1e-06; • You need to do at least one PISO correction. Increasing the
24 default Gauss linear; 24 relTol 0; number of PISO correctors will improve the stability and
25 //default cellMDLimited Gauss linear 1; • These are the laplacianSchemes and 38 }
26 39 accuracy of the solution at a higher computational cost.
27 grad(p) Gauss linear; snGradSchemes schemes that you will use most of the 40 pFinal
28
29
}
times: 41
42
{
$p;
• For orthogonal meshes, 1 PISO correction is ok. But as
30 divSchemes
• orthogonal: second order accurate, bounded on
43 relTol 0; most of the time you will deal with non-orthogonal meshes,
31 { 44 }
32 default none; perfect meshes, without non-orthogonal 45 doing 2 PISO corrections is a good choice.
33 //div(phi,U) Gauss linearUpwind default; 46 U
34 div(phi,U) Gauss linear; corrections. 47 { • If you are using a method with non-orthogonal corrections
35 } 48 solver smoothSolver;
36 • corrected: second order accurate, bounded 49 smoother symGaussSeidel; (corrected or limited 1-0.5), you need to define the number
37 laplacianSchemes 50 tolerance 1e-08; of non-orthogonal corrections (nNonOrthogonalCorrectors).
38 { depending on the quality of the mesh, with non- 51 relTol 0;
39 default Gauss linear orthogonal; 52 }
40 //default Gauss linear limited 1;
orthogonal corrections. 53 } • If you use 0 nNonOrthogonalCorrectors, you are
41 } 54
42 • limited : second order accurate, bounded 55 PISO
computing the initial approximation using central differences
43 interpolationSchemes depending on the quality of the mesh, with non- 56 { (accurate but unstable), with no explicit correction.
44 { 57 nCorrectors 1;
45 default linear; orthogonal corrections. 58 nNonOrthogonalCorrectors 0;
• To take into account the non-orthogonality of the mesh, you
46 } 59 pRefCell 0;
47 • uncorrected: second order accurate, without 60 pRefValue 0; will need to increase the number of corrections (you get
48 snGradSchemes 61 }
49 { non-orthogonal corrections. Stable but more better approximations using the previous correction).
50 default orthogonal;
51 //default limited 1;
diffusive than limited and corrected. • Usually 2 nNonOrthogonalCorrectors is ok.
52 }

745 746
Numerical playground Numerical playground
What are we going to do?
• We will now illustrate a few of the discretization schemes available in • This is the same case as the one we used during the first tutorial session.
OpenFOAM® using a model case. • 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
• We will use the lid-driven square cavity case to study the effect of grading mesh?
and non-orthogonality on the accuracy of the solution • We will use this case to learn how to adjust the numerical schemes according to mesh non-orthogonality and
grading.
• This case is located in the directory:
• After finding the numerical solution we will do some sampling and plotting.

$PTOFC/101FVM/nonorthoCavity/ Running the case


• You will find this tutorial in the directory $PTOFC/101FVM/nonorthoCavity
• In the terminal window type:

1. $> foamCleanTutorials
• 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. 2. $> blockMesh
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh, 3. $> checkMesh
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case 4. $> icoFoam | log
automatically by typing in the terminal, for example, sh run_solver.
5. $> postProcess -func sampleDict -latestTime
• 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. 6. $> gnuplot gnuplot/gnuplot_script

• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases. 7. $> paraFoam
747 748

Numerical playground Numerical playground


To run the case, follow these steps • When it comes to laplacianSchemes and snGradSchemes this is how we
• First run the case using the original dictionaries. Did it crash right? proceed most of the times (a robust setup),
• 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 laplacianSchemes
{
more time-steps, right? default Gauss linear limited 1; PISO
• Now increase the number of PISO corrections to 2 (nCorrectors). Did it run? } {
nCorrectors 2;
• Basically we enabled non-orthogonal corrections, we computed better approximations of the snGradSchemes nNonOrthogonalCorrectors 1;
gradients, and we increased the number of PISO corrections to get better predictions of the field { }
default limited 1;
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 • This method works fine for meshes with non-orthogonality less than 75.
value of nNonOrthogonalCorrectors.
• We are using a method that uses a wider stencil to compute the Laplacian, this method is more
• If the non-orthogonality is more than 75, you should consider using limited
stable but a little bit more diffusive. Did it run? 0.5, and increasing nCorrectors and nNonOrthogonalCorrectors.
• At this point, compare the solution obtained with corrected and uncorrected schemes. Which • When the non-orthogonality is more than 85, the best solution is to redo the
one is more diffusive? mesh.
749 750
Numerical playground 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) Seesaw:
• 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 Sod’s shock tube.
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)
• Try to break the solver and interpret the output screen. You are allow to modify the original mesh and use any
combination of discretization schemes.

751 752

Numerical playground Numerical playground


Sod’s shock tube High Purity Photolysis Shock Tube (NASA 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.

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
753 Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose. 754
Numerical playground Numerical playground
Sod’s shock tube Sod’s shock tube

All walls are slip


Pressure field Density field

Boundary conditions and initial conditions Analytical solution


Velocity magnitude field Temperature field
755 756

Numerical playground Numerical playground


What are we going to do?
• We will now illustrate a few of the discretization schemes available in • Now is your turn.
OpenFOAM® using a severe model case. • You are asked to select the best discretization scheme for the physics involve.
• We will use the Sod’s shock tube case. Remember: accuracy, stability and boundedness.
• This case is located in the directory: • 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.
$PTOFC/101FVM/shockTube/ • You can start using the original dictionaries.
• To find the numerical solution we will use sonicFoam.
• sonicFoam is a transient solver for trans-sonic/supersonic, laminar or turbulent flow
• In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
of a compressible gas.
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, • After finding the numerical solution we will do some sampling.
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. • At the end, we will do some plotting (using gnuplot or Python) and scientific
• We highly recommend you to open the README.FIRST file and type the commands in the terminal, in this visualization.
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.
757 758
Numerical playground Numerical playground
Running the case Exercises
• You will find this tutorial in the directory $PTOFC/101FVM/schockTube • Run the case using different time discretization schemes.
• Before running the case, you will need to choose the discretization scheme. • Run the case using different gradient discretization schemes.
• In the terminal window type:
• Run the case using different convective discretization schemes for the term div(phi,U).
1. $> foamCleanTutorials • Run the case using different convective discretization schemes for the terms div(phi,e) and div(phi,K). What
2. $> blockMesh are the variables e and K?
3. $> checkMesh • Extend the case to 2D and 3D. Do you get the same solution?
4. $> rm –rf 0 • Try to run a 2D case using a triangular mesh and adjust the numerical scheme to get an accurate and stable
5. $> cp –r 0_org 0 solution.
$> setFields • Try to run the 1D case using an explicit solver. For the same CFL number, do you have the same time step
6.
size as for the implicit solver?
7. $> sonicFoam | tee log
(Hint: look for the solver with the word Central)
8. $> foamCalc mag U
• Try to break the solver (this is extremely easy in this case). You are allowed to modify the original mesh and
9. $> postProcess -func sampleDict -latestTime use any combination of discretization schemes.
10. $> 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:

1. $> cd python
2. $> python3 sodschocktube.py

• The Python script will save four .png files with the solution. Feel free to explore and adapt the Python script to your needs.
• Remember, Python (version 3)must be installed in order to use the script
759 760

Some FVM/CFD references


• As we mentioned earlier this is not a FVM/CFD course, but we highly advise you to take some time and study the theory in depth.
• There is vast amount of literature in the field of FVM/CFD. We will give you some of our favorite references, which are closed related to what
you will find in OpenFOAM®.
• Therefore, we are involuntarily omitting other references which are equally or even more important.
• The Finite Volume Method in Computational Fluid Dynamics: An Advanced Introduction With OpenFOAM and Matlab
F. Moukalled, L. Mangani, M. Darwish. 2015, Springer-Verlag
• Finite Volume Methods for Hyperbolic Problems
R. Leveque. 2002, Cambridge University Press
• Computational Gasdynamics
C. Laney. 1998, Cambridge University Press
• Computational Techniques for Multiphase Flows
G. H. Yeoh, J. Tu. 2009, Butterworth-Heinemann
Module 7
• An Introduction to Computational Fluid Dynamics
H. K. Versteeg, W. Malalasekera. 2007, Prentice Hall Highlights – Implementing boundary
• Computational Fluid Dynamics: Principles and Applications
J. Blazek. 2006, Elsevier Science
• Computational Methods for Fluid Dynamics
conditions and initial conditions using
J. H. Ferziger, M. Peric. 2001, Springer
• Numerical Heat Transfer and Fluid Flow
S. Patankar. 1980, Taylor & Francis
codeStream
• A Finite Volume Method for the Prediction of Three-Dimensional Fluid Flow in Complex Ducts
M. Peric. PhD Thesis. 1985. Imperial College, London
• Error analysis and estimation in the Finite Volume method with applications to fluid flows
H. Jasak. PhD Thesis. 1996. Imperial College, London
• Computational fluid dynamics of dispersed two-phase flows at high phase fractions
H. Rusche. PhD Thesis. 2002. Imperial College, London
• High Resolution Schemes Using Flux Limiters for Hyperbolic Conservation Laws
P. K. Sweby SIAM Journal on Numerical Analysis, Vol. 21, No. 5. (Oct., 1984), pp. 995-1011

761 762
Roadmap 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:
1. codeStream – Highlights
• Use codeStream.
2. Implementing boundary conditions using • Use high level programing.
codeStream • Use an external library (e.g., swak4foam).
3. Solution initialization using codeStream • 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.
763 764

codeStream – Highlights codeStream – Highlights


codeStream – Initial conditions • Hereafter we will work with codeStream, which will let us program directly in the input
• When it comes to initial conditions, you can use the utility setFields. dictionaries.
• This utility is very flexible, you can even read STL files and use them to initialize fields. • With codeStream, we will implement our own boundary conditions and initial
conditions without going thru the hustle and bustle of high-level programming.
• But again, it may happen that you can not get the desired results.
• If you are interested in high level programming, refer to the supplements.
• As for boundary conditions, to implement your own initials conditions you have three options:
• Use codeStream. • In the supplemental slides, we address the following topics: building blocks,
implementing boundary conditions using high level programming, modifying
• Use high level programing.
applications, implementing an application from scratch, and adding the scalar
• Use an external library (e.g., swak4foam). transport equation to icoFoam.
• codeStream is the simplest way to implement initial conditions, and most of the times you will • High level programming requires some knowledge on C++ and OpenFOAM® API
be able to code initial conditions with no problem.
library. This is the hard part of programming in OpenFOAM®.
• 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.
• Before doing high level programming, we highly recommend you to try with
codeStream, most of the time it will work.
• Hereafter, we are going to work only with codeStream.
• Also, before modifying solvers or trying to implement your own solvers, understand
• Using high level programming is a little bit trickier, and we guarantee you that 99% of the times
the theory behind the FVM.
codeStream will work.
• We are not going to work with swak4Foam because it is an external library that is not officially • Remember, you can access the API documentation in the following link,
supported by the OpenFOAM foundation®. However, it works very well and is relatively easy to https://cpp.openfoam.org/v5/
use.
765 766
Roadmap 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
1. codeStream – Highlights generate the dynamic code.
• The source code and binaries are automatically generated and copied in the
2. Implementing boundary conditions using directory dynamicCode of the current case.
codeStream
• The source code is compiled automatically at run-time.
3. Solution initialization using codeStream • 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,
but have in mind that codeStream can be used in any dictionary.

767 768

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Body of the codeStream directive for boundary conditions Implementation of a parabolic inlet profile using codeStream

patch-name
• Let us implement a parabolic inlet profile.
Patch name
{
type fixedValue;
• The firs step is identifying the patch, its location and the dimensions.
value #codeStream
Use codeStream to set the value
{ of the boundary condition • You can use paraview to get all visual references.
codeInclude
#{ Outlet
#include "fvCFD.H" Files needed for compilation pressure-outlet-7
#};

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 boundary condition Inlet
#}; at time zero velocity-inlet-5

code
#{ Insert your code here.
At this point, you need to know
#}; how to access mesh information Inlet
}; Bounds of velocity-inlet-5 boundary patch
velocity-inlet-6
}
769
Parabolic inlet profile 770
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codeStream • The codeStream BC in the body of the file U is as follows,
• We will use the following formula to implement the parabolic inlet profile velocity-inlet-5 Patch name
{
type fixedValue;
value #codeStream
{
codeInclude
#{
#include "fvCFD.H"
#};
• For this specific case c is the patch midpoint in the y direction (8), r is the patch Depending of what are you trying
semi-height or radius (8) and Umax is the maximum velocity. codeOptions to do, you will need to add new
#{ files, options and libraries.
• We should get a parabolic profile similar to this one, -I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude For most of the cases, this part is
#};
always the same.
codeLibs
#{
-lmeshTools \
-lfiniteVolume
#};

code
#{ Insert your code here.
At this point, you need to know
#}; how to access mesh information
};
}
771 772

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• The code section of the codeStream BC in the body of the file U is as follows, • The code section of the codeStream BC in the body of the file U is as follows,

To access boundary mesh information


1 code 1 code Index used to access the
2 #{ 2 #{ y coordinate
3 const IOdictionary& d = static_cast<const IOdictionary&> 3 ... 0→x
4 ( 4 ...
5 dict.parent().parent() 5 ...
1→y
6 ); 6 const scalar pi = constant::mathematical::pi; 2→z
7 7 const scalar U_0 = 2.; //maximum velocity
8 const fvMesh& mesh = refCast<const fvMesh>(d.db()); 8 const scalar p_ctr = 8.; //patch center
9 const label id = mesh.boundary().findPatchID("velocity-inlet-5"); 9 const scalar p_r = 8.; //patch radius
10 const fvPatch& patch = mesh.boundary()[id]; 10
11 11 forAll(U, i) //equivalent to for (int i=0; patch.size()<i; i++)
12 vectorField U(patch.size(), vector(0, 0, 0)); 12 {
13 13 const scalar y = patch.Cf()[i][1];
14 ... 14 U[i] = vector(U_0*(1-(pow(y - p_ctr,2))/(p_r*p_r)), 0., 0.);
15 ... Remember to update this value with the 15 }
16 ... 16 Assign input profile to vector field U (component x)
actual name of the patch
17 #}; 17 U.writeEntry("", os);
18 #};

• Lines 3-11, are always standard, they are used to access boundary mesh information.
• In lines 6-17 we implement the new boundary condition.
• In lines 3-6 we access the current dictionary.
• In lines 6-9 we declare a few constant needed in our implementation.
• In line 8 we access the mesh database.
• In lines 11-15 we use a forAll loop to access the boundary patch face centers and to assign the velocity profile
• 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
values. Notice the U was previously initialized.
the patch).
• In line 13 we get the y coordinates of the patch faces center.
• In line 10 using the label id of the patch, we access the boundary mesh information.
• In line 14 we assign the velocity value to the patch faces center.
• 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. 773
• In line 17 we write the U values to the dictionary. 774
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codeStream Implementation of a parabolic inlet profile using codeStream
• This case is ready to run, the input files are located in the directory • If everything went fine, you should get something like this
$PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet
• To run the case, type in the terminal,

1. $> cd $PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet

2. $> foamCleanTutorials
3. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh

4. $> icoFoam | tee log


5. $> paraFoam

• The codeStream boundary condition is implemented in the file 0/U.

775 776

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
codeStream works with scalar and vector fields Implementation of a paraboloid inlet profile using codeStream
• We just implemented the input parabolic profile using a vector field. • Let us work in a case a little bit more complicated, a paraboloid input profile.
• You can do the same using a scalar field, just proceed in a similar way. • As usual, the first step is to get all the spatial references.
• 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
Inlet
8 forAll(S, i) Loop using scalar field size auto3
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 S.writeEntry("", os);
Write output to input
15 #}; dictionary

Bounds of auto3 boundary patch


Paraboloid inlet profile
Notice that the name of the field does not need to be the same as the name of the input dictionary
777 778
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a paraboloid inlet profile using codeStream • The codeStream BC in the body of the file U is as follows,
• We will implement the following equation in the boundary patch auto3.
auto3 Patch name
{
type fixedValue;
value #codeStream
{
codeInclude
#{
#include "fvCFD.H"
#};
For most of the cases, this part is
codeOptions always the same. But depending of
#{
what are you trying to do, you will
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude need to add more files, options and
#}; libraries.

codeLibs
#{
-lmeshTools \
-lfiniteVolume
#};
Insert your code here.
code
#{
We will implement the following
equation
#};
};
}
779 780

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• Hereafter, we only show the actual implementation of the codeStream boundary Implementation of a paraboloid inlet profile using codeStream
condition.
• This case is ready to run, the input files are located in the directory
• The rest of the body is a template that you can always reuse. Including the section of $PTOFC/101programming/codeStream_BC/3Delbow_Uparaboloid/
how to access the dictionary and mesh information.
• To run the case, type in the terminal,
• 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. $> cd $PTOFC/101programming/codeStream_BC/3Delbow_Uparaboloid/
1 code 2. $> foamCleanTutorials
2 #{
3 ... 3. $> gmshToFoam ../../../meshes_and_geometries/gmsh_elbow3d/geo.msh
4 ...
5 ...
6 vectorField U(patch.size(), vector(0, 0, 0) );
4. $> autoPatch 75 -overwrite
Initialize vector field
7
8 const scalar s = 0.5; Initialize scalar 5. $> createPatch -overwrite
9
10 forAll(U, i) 6. $> renumberMesh -overwrite
11 {
12 const scalar x = patch.Cf()[i][0]; Access faces center 7. $> icoFoam | tee log
13 const scalar y = patch.Cf()[i][1]; coordinates (x, y, and z)
14 const scalar z = patch.Cf()[i][2]; 8. $> paraFoam
15
16 U[i] = vector(-1.*(pow(z/s, 2) + pow((y-s)/s,2) - 1.0), 0, 0);
17 }
18
• The codeStream boundary condition is implemented in the file 0/U.
19 U.writeEntry("", os);
20 #};
781 782
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a paraboloid inlet profile using codeStream codedFixedValue and codedMixed boundary conditions
• If everything went fine, you should get something like this • 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.
783 784

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Body of the codedFixedValue boundary conditions • The code section of the codeStream BC in the body of the file U is as follows,

patch-name Patch name 1 code


{ 2 #{
type codedFixedValue; Use codedFixedValue and 3 const fvPatch& boundaryPatch = patch();
value uniform (0 0 0); initializations 4 const vectorField& Cf = boundaryPatch.Cf();
5 vectorField& field = *this;
Unique name of the new boundary 6
redirectType name_of_BC; condition. 7 scalar U_0 = 2, p_ctr = 8, p_r = 8;
If you have more codedFixedValue 8
BC, the names must be different 9 forAll(Cf, faceI)
codeOptions 10 {
#{ 11 field[faceI] = vector(U_0*(1-(pow(Cf[faceI].y()-p_ctr,2))/(p_r*p_r)),0,0);
-I$(LIB_SRC)/finiteVolume/lnInclude \ Compilation options 12 }
-I$(LIB_SRC)/meshTools/lnInclude 13 #};
#};

codeInclude
#{ • Lines 3-5, are always standard, they give us access to mesh and field information in the patch.
#include "fvCFD.H"
#include <cmath> Files needed for compilation • The coordinates of the faces center are stored in the vector field Cf (line 4).
#include <iostream> • 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 this section we do the actual
code implementation of the boundary • In line 7 we initialize a few constants that will be used in our implementation.
#{ condition. • In lines 9-12 we use a forAll loop to access the boundary patch face centers and to assign the velocity profile
This is the only part of the body values.
#}; that you will need to change. The
} • In line 11 we do the actual implementation of the boundary profile (similar to the codeStream case). The
rest of the body is a template that
vector field was initialize in line 5.
you can always reuse. 785 786
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
codedFixedValue and codedMixed boundary conditions • Let us add time dependency to the parabolic profile.
• As you can see, the syntax and use of the codedFixedValue and codedMixed
1 code
boundary conditions is much simpler than codeStream. 2 #{
3 const fvPatch& boundaryPatch = patch();
• You can use these instructions as a template. At the end of the day, you only need to 4 const vectorField& Cf = boundaryPatch.Cf();
modify the code section. 5 vectorField& field = *this;
6
• Depending of what you want to do, you might need to add new headers and 7 scalar U_0 = 2, p_ctr = 8, p_r = 8;
8
compilation options. 9 scalar t = this->db().time().value(); Time
10
• Remember, is you are working with a vector, you need to use vector fields. Whereas, 11 forAll(Cf, faceI)
if you are working with scalars, you need to use scalars fields. 12 {
13 field[faceI] = vector(sin(t)*U_0*(1-(pow(Cf[faceI].y()-p_ctr,2))/(p_r*p_r))),0,0);
• One disadvantage of these boundary conditions, is that you can not visualize the 14 }
15 #};
fields at time zero. You will need to run the simulation for at least one iteration. Time dependency

• On the positive side, accessing time and other values from the simulation database is
straightforward. • This implementation is similar to the previous one, we will only address how to deal with time.
• Time can be accessed by adding the following statement, • 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 initialize in line 5 and time is accessed in line 9.
this->db().time().value() • In this case, we added time dependency by simple multiplying the parabolic profile by the
function sin(t).
787 788

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codedFixedValue Implementation of a parabolic inlet profile using codedFixedValue
• This case is ready to run, the input files are located in the directory • If everything went fine, you should get something like this
$PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet_timeDep
• To run the case, type in the terminal,

1. $> cd $PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet_timeDep

2. $> foamCleanTutorials
3. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh

4. $> icoFoam | tee log


5. $> paraFoam

• The codeStream boundary condition is implemented in the file 0/U.

www.wolfdynamics.com/wiki/BCIC/elbow_unsBC1.gif

789 790
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Filling a tank using codedFixedValue • Definition of the vector field boundary condition (dictionary file U),
• Let us do a final example.
Name of the patch where we want to implement the boundary condition
• We will deal with scalar and vector fields at the same Water enters here
time. This is a face selection in a single boundary patch
1 leftWall Use codedFixedValue BC and initialize value.
• We will use codedFixedValue. 2 { The initialization is only needed for paraview
3 type codedFixedValue; in order to visualize something at time zero.
• For simplicity, we will only show the code section of the 4 value uniform (0 0 0);
input files. 5 redirectType inletProfile1; Unique name of the BC
6
• Remember, the rest of the body can be used as a Do not use the same name in other patches
7 code
template. 8 #{
• And depending of what you want to do, you might need 9 const fvPatch& boundaryPatch = patch(); Access boundary mesh
10 const vectorField& Cf = boundaryPatch.Cf(); information and initialize
to add new headers, libraries, and compilation options.
11 vectorField& field = *this; vector field field
• Hereafter we will setup an inlet boundary condition in a 12
portion of an existing patch. 13 scalar minz = 0.4;
14 scalar maxz = 0.6;
• By using codedFixedValue BC, we do not need to 15 scalar miny = 0.5; Initialize variables
modify the actual mesh topology. 16 scalar maxy = 0.7;
17
• We will assign a velocity field and a scalar field to a set 18 scalar t = this->db().time().value(); Access time
of faces (dark area in the figure). ...
...
• We are going to simulate filling a tank with water. ...
40 #};
• We will use the solver interFoam. 41 }
The tank is initially empty

791 792

Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• Definition of the vector field boundary condition (dictionary file U), • 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 Name of the patch where we want to implement the boundary condition
8 #{
... 1 leftWall Use codedFixedValue BC and initialize value.
... Loop using size of boundary patch (Cf) and iterator 2 { The initialization is only needed for paraview
... faceI. 3 type codedFixedValue;
in order to visualize something at time zero.
19 This is equivalent to: 4 value uniform 0;
20 forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++) 5 redirectType inletProfile2; Unique name of the BC
21 { 6 Do not use the same name in other patches
22 7 code
23 if ( 8 #{
24 (Cf[faceI].z() > minz) && 9 const fvPatch& boundaryPatch = patch(); Access boundary mesh
Code section. The actual implementation of
Use conditional structure to 10 const vectorField& Cf = boundaryPatch.Cf(); information and initialize
25 (Cf[faceI].z() < maxz) &&
26 (Cf[faceI].y() > miny) && select faces according to the 11 scalarField& field = *this; scalar field field
27 (Cf[faceI].y() < maxy) variables defined in lines 13-16 12
28 ) 13 field = patchInternalField(); Assign value from the internal field to the patch
14
the BC is done in this section

29 {
30 if ( t < 1.) 15 scalar minz = 0.4;
31 { Use conditional structure to 16 scalar maxz = 0.6;
17 scalar miny = 0.5; Initialize variables
32 field[faceI] = vector(1,0,0); add time dependency and
33 } 18 scalar maxy = 0.7;
assign values to the 20
34 else
selected faces. 21 scalar t = this->db().time().value(); Access time
35 {
36 field[faceI] = vector(0,0,0); The variable field was 22
37 } initialize in line 11. ...
38 } ...
39 } ...
40 #}; 42 #};
41 } 43 }
793 794
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• Definition of the scalar field boundary condition (dictionary file alpha.water), Implementation of a parabolic inlet profile using codedFixedValue
• This case is ready to run, the input files are located in the directory
7 code Code section. The actual implementation of the BC is done in this section
8 #{ $PTOFC/101programming/codeStream_BC/fillBox_BC/
...
...
Loop using size of boundary patch (Cf) and iterator • To run the case, type in the terminal,
... faceI.
22 This is equivalent to:
23 forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++) 1. $> cd $PTOFC/101programming/codeStream_BC/fillBox_BC/
24 {
25 if ( 2. $> foamCleanTutorials
26 (Cf[faceI].z() > minz) && Use conditional structure to
27 (Cf[faceI].z() < maxz) && select faces according to the 3. $> blockMesh
28 (Cf[faceI].y() > miny) &&
variables defined in lines 13-16
29 (Cf[faceI].y() < maxy) 4. $> decomposePar
30 )
31 { $> mpirun -np 4 interFoam -parallel | tee log
32 if ( t < 1.)
5.
33 {
34 field[faceI] = 1.;
Use conditional structure to add 6. $> reconstructPar
time dependency and assign
35 }
36 else
values to the selected faces. 7. $> paraFoam
37 { The variable field was initialize in
38 field[faceI] = 0.; line 11.
39 } • As you can see, we can also run in parallel with no problem.
40 }
41 } • FYI, the stand alone version of Paraview does not handle codedFixedValue BC.
42 #};
43 } • To visualize the results, you need to use paraFoam with no options (avoid the option
795 –builtin). 796

Implementing boundary conditions using codeStream Roadmap


Implementation of a parabolic inlet profile using codedFixedValue
• If everything went fine, you should get something like this

00

00

00
1. codeStream – Highlights
0 02
2. Implementing boundary conditions using
codeStream
0 01

3. Solution initialization using codeStream


0
0 02 0 0 0 1 12 1 1 1 2

Visualization of water phase Volume integral of water entering the


(alpha.water) domain
www.wolfdynamics.com/wiki/BCIC/filltank1.gif
797 798
Solution initialization using codeStream Solution initialization using codeStream
• When it comes to initial conditions, you can use the utility setFields. Body of the codeStream directive for initial conditions
• This utility is very flexible, you can even read STL files and use them to internalField #codeStream Use codeStream to set the value
initialize your fields. { of the initial conditions
{
• But in case that you can not get the desired results using setFields, you codeInclude
#{
can implement your own initial conditions using codeStream. #include "fvCFD.H" Files needed for compilation

Initial conditions
#};
• To implement initial conditions using codeStream, we proceed in a similar
codeOptions
way as for boundary conditions. #{
-I$(LIB_SRC)/finiteVolume/lnInclude \ Compilation options
• The source code and binaries are automatically generated and copied in the -I$(LIB_SRC)/meshTools/lnInclude
#};
directory dynamicCode of the current case.
codeLibs
Libraries needed for compilation.
• The source code is compiled automatically at run-time. #{
Needed if you want to visualize the
-lmeshTools \
• The use of codeStream is a very good alternative to avoid high level -lfiniteVolume output of the initial conditions at
time zero
#};
programming of initial conditions or the use of external libraries.
code
• Hereafter we will use codeStream to implement new initial conditions. #{
Insert your code here.
#}; At this point, you need to know
}; how to access internal mesh
} information

799 800

Solution initialization using codeStream Solution initialization using codeStream


Implementation of an elliptic initialization using codeStream • The codeStream IC in the body of the file alpha.phase1 is as follows,
• Let us implement an elliptic initialization using codeStream. internalField #codeStream Use codeStream to set the value
{ of the initial conditions
• The firs step is to know your domain and identify the region that you want to initialize. {
codeInclude
• Then you will need to do a little bit of math to get the expression for the initialization. #{
#include "fvCFD.H"
• 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.
codeOptions Depending of what are you trying
Initialization using STL

#{ to do, you will need to add new


-I$(LIB_SRC)/finiteVolume/lnInclude \ files, options and libraries.
-I$(LIB_SRC)/meshTools/lnInclude
Phase 2 #};
For most of the cases, this part is
codeLibs always the same.
#{
-lmeshTools \
-lfiniteVolume
#};

Phase 1 code
#{
Insert your code here.
#}; At this point, you need to know
}; how to access internal mesh
} information
Initialization using codeStream Initialization using a STL with setFields

801 802
Solution initialization using codeStream Solution initialization using codeStream
• The code section of the codeStream IC in the body of the file alpha.phase1 is as follows, Implementation of an elliptic initialization using codeStream

Access internal mesh information


code • This case is ready to run, the input files are located in the directory
#{ $PTOFC/101programming/codeStream_INIT/elliptical_IC
const IOdictionary& d = static_cast<const IOdictionary&>(dict);
const fvMesh& mesh = refCast<const fvMesh>(d.db());
• To run the case, type in the terminal,
scalarField alpha(mesh.nCells(), 0.); Initialize scalar field to zero
scalar he = 0.5;
1. $> cd $PTOFC/101programming/codeStream_INIT/elliptical_IC
Initialize variables
scalar ke = 0.5;
scalar ae = 0.3; 2. $> foamCleanTutorials
scalar be = 0.15; forAll loop to access cell centers and to assign alpha values.
Notice the alpha was previously initialized.
3. $> blockMesh
forAll(alpha, i) The size of the loop is defined by alpha and the iterator is i.
{ 4. $> rm –rf 0
const scalar x = mesh.C()[i][0];
const scalar y = mesh.C()[i][1]; Access cell centers coordinates 5. $> cp –r 0_org 0
const scalar z = mesh.C()[i][2];
Assign value to alpha

6. $> paraFoam
if ( pow(y-ke,2) <= ((1 - pow(x-he,2)/pow(ae,2) )*pow(be,2)) )

If this condition is true, do the


{ $> interFoam | tee log
alpha[i] = 1.;
7.
}
$> paraFoam

following statement
} 8.
alpha.writeEntry("", os);
#};
• In step 6, we launch paraFoam to visualize the initialization.
Write output to input dictionary
• FYI, you can run in parallel with no problem.
803 804

Solution initialization using codeStream Solution initialization using codeStream


Implementation of an elliptic initialization using codeStream Elliptic initialization using setFields
• If everything went fine, you should get something like this • 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
codeStream initialization setFields initialization Computational domain
Visualization of volume fraction (alpha.phase1) Visualization of volume fraction (alpha.phase1)
www.wolfdynamics.com/wiki/BCIC/bubble_zeroG.gif www.wolfdynamics.com/wiki/BCIC/bubble_zeroG_SF.gif

Surface tension driven flow - Bubble in a zero gravity flow using interFoam
805 806
Solution initialization using codeStream Solution initialization using codeStream
The setFieldsDict dictionary Elliptic initialization using setFields
• This case is ready to run, the input files are located in the directory
defaultFieldValues
( $PTOFC/101programming/codeStream_INIT/elliptical_IC
volScalarFieldValue alpha.phase1 0 Initialize the whole domain to zero
); • To run the case, type in the terminal,
regions
setFields method to read STL files.
( If you want to know all the options 1. $> cd $PTOFC/101programming/codeStream_INIT/elliptical_IC
available use a word that does not exist
surfaceToCell in the enumerator list (e.g. banana) 2. $> foamCleanTutorials
{
file "./geo/ellipse.stl"; Location of the STL file to read 3. $> blockMesh
outsidePoints ((0.5 0.85 0)); A point located outside the STL 4. $> rm –rf 0
includeInside true; Use what is inside the STL 5. $> cp –r 0_org 0
includeOutside false; Use what is outside the STL 6. $> setFields
includeCut false; Include cells cut by the STL
7. $> paraFoam
fieldValues
(
volScalarFieldValue alpha.phase1 1 Initialize this value. • At this point, compare this initialization with the previous one.
); In this case the initialization will be inside
the STL • Also, feel free to launch the simulation using interFoam.
}
);
807 808

Solution initialization using codeStream Solution initialization using codeStream


Rayleigh-Taylor instability initialization • The code section of the codeStream IC in the body of the file alpha.phase1 is as follows,

code Access internal mesh information


#{
• Let us study the Rayleigh-Taylor const IOdictionary& d = static_cast<const IOdictionary&>(dict);
instability. const fvMesh& mesh = refCast<const fvMesh>(d.db());

• In this case, we have two phases with scalarField alpha(mesh.nCells(), 0.); Initialize scalar field to zero
different physical properties (one phase
forAll(alpha, i)
is heavier).
Assign value to alpha
{
• To onset this instability, we need to const scalar x = mesh.C()[i][0];
const scalar y = mesh.C()[i][1];
Access cell centers coordinates
perturbate somehow the interface
between the two phases. if (y >= -0.05*cos(2*constant::mathematical::pi*x))
{
• We will use codeStream to initialize the alpha[i] = 1.;
}
two phases. }
• For simplicity, we will only show the alpha.writeEntry("", os);
code section of the input files. #}; Write output to input dictionary
• The entries codeInclude, codeOptions,
and codeLibs, are the same most of the
times. • For simplicity, we only show the code section.
• The rest of the body of the codeStream IC is a template.

809 810
Solution initialization using codeStream Solution initialization using codeStream
Rayleigh-Taylor instability initialization Rayleigh-Taylor instability initialization
• This case is ready to run, the input files are located in the directory • If everything went fine, you should get something like this
$PTOFC/101programming/codeStream_INIT/rayleigh_taylor
• To run the case, type in the terminal,

1. $> cd $PTOFC/101programming/codeStream_INIT/rayleigh_taylor
2. $> foamCleanTutorials
3. $> blockMesh
4. $> interFoam | tee log
5. $> paraFoam

Initial conditions Visualization of volume fraction, static pressure and velocity


• FYI, you can run in parallel with no problem. magnitude
www.wolfdynamics.com/wiki/BCIC/rayleigh_taylor_ins1.gif

811 812

Solution initialization using codeStream Solution initialization using codeStream


Filling a tank using codeStream and codedFixedValue • The code section of the codeStream IC in the body of the file alpha.water is as follows,

• Let us do a final example.


internalField #codeStream
Use codeStream to set the
• We will implement BCs and ICs at the same. { value of the initial conditions

Access internal mesh information


...
• 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 code
codedFixedValue). #{
const IOdictionary& d = static_cast<const IOdictionary&>(dict);
const fvMesh& mesh = refCast<const fvMesh>(d.db());
Water enters here
This is a single boundary patch scalarField alpha(mesh.nCells(), 0.); Initialize scalar field to zero
forAll(alpha, i)
{
const scalar x = mesh.C()[i][0];
const scalar y = mesh.C()[i][1]; Access cell centers
const scalar z = mesh.C()[i][2]; coordinates

if (y <= 0.2)
{ Assign value to alpha according to
alpha[i] = 1.; conditional structure
}
}

alpha.writeEntry("", os); Write output to input dictionary


Initial water level
#};

813 814
Solution initialization using codeStream Solution initialization using codeStream
• The code section of the codeFixedValue BC in the body of the file U is as follows, • The code section of the codeFixedValue BC in the body of the file U is as follows,

Name of the patch where we want to implement the boundary condition code Code section. The actual implementation of the BC is done here
#{
...
leftWall Use codedFixedValue BC and initialize value. ... Loop using size of boundary patch (Cf) and iterator
{ The initialization is only needed for paraview ... faceI.
type codedFixedValue; This is equivalent to:
in order to visualize something at time zero.
value uniform (0 0 0); forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++)
Unique name of the BC {
redirectType inletProfile1;
Do not use the same name in other patches
if (
code Code section. The actual implementation of the BC is done here (Cf[faceI].z() > min) &&
#{ (Cf[faceI].z() < max) && Use conditional structure to
const fvPatch& boundaryPatch = patch(); Access boundary mesh (Cf[faceI].y() > min) && select faces.
const vectorField& Cf = boundaryPatch.Cf(); information and initialize (Cf[faceI].y() < max)
vectorField& field = *this; vector field field )
{
scalar min = 0.5; if ( t < 2.)
scalar max = 0.7; Initialize variables
{
field[faceI] = vector(1,0,0); Use conditional structure to
scalar t = this->db().time().value(); Access time } add time dependency and
... else
... assign values to the
{
... field[faceI] = vector(0,0,0); selected faces.
#}; }
} }
}
#};

815 816

Solution initialization using codeStream Solution initialization using codeStream


• The code section of the codeFixedValue BC in the body of the file alpha.water is as follows, • The code section of the codeFixedValue BC in the body of the file alpha.water is as follows,

Name of the patch where we want to implement the boundary condition code Code section. The actual implementation of the BC is done here
#{
leftWall Use codedFixedValue BC and initialize value. ...
{ Loop using size of boundary patch (Cf) and iterator
The initialization is only needed for paraview ...
type codedFixedValue;
in order to visualize something at time zero. ... faceI.
value uniform 0; This is equivalent to:
Unique name of the BC forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++)
redirectType inletProfile2; {
Do not use the same name in other patches
if (
(Cf[faceI].z() > min) &&
code Code section. The actual implementation of the BC is done here (Cf[faceI].z() < max) && Use conditional structure to
#{ (Cf[faceI].y() > min) && select faces
const fvPatch& boundaryPatch = patch(); Access boundary mesh (Cf[faceI].y() < max)
const vectorField& Cf = boundaryPatch.Cf(); information and initialize )
scalarField& field = *this; scalar field field {
if ( t < 2.)
{
field = patchInternalField(); Assign value from the internal field to the patch field[faceI] = 1.;
Use conditional structure to add
}
scalar min = 0.5; else time dependency and assign
scalar max = 0.7;
Initialize variables
{ values to the selected faces.
field[faceI] = 0.;
scalar t = this->db().time().value(); Access time }
... }
... }
... #};
#};
}
817 818
Solution initialization using codeStream
Filling a tank using codeStream and codedFixedValue
• If everything went fine, you should get something like this

02
Module 8
02

Advanced physics
Turbulence modeling – Multiphase flows –
02

0 22

02
Compressible flows – Moving bodies –
01
0 0 1 1 2 2

Source terms – Passive scalars

Visualization of water phase (alpha.water) Volume integral of water entering


www.wolfdynamics.com/wiki/BCIC/filltank2.gif the domain

819 820

• In this module, we will deal with advanced modeling capabilities.


Roadmap
• 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 the A crash introduction to:
models.
1. Turbulence modeling in OpenFOAM®
2. Multiphase flows modeling in
“Essentially, all models are wrong,
OpenFOAM®
but some are useful”
3. Compressible flows in OpenFOAM®
G. E. P. Box 4. Moving bodies in OpenFOAM®
5. Source terms in OpenFOAM®
George Edward Pelham Box
18 October 1919 – 28 March 2013. Statistician, who 6. Scalar transport pluggable solver
worked in the areas of quality control, time-series
analysis, design of experiments, and Bayesian inference.
He has been called “one of the great statistical minds of
the 20th century”.
821 822
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

What is turbulence?
• For the purpose of this training, let us state the following:
• Turbulence is an unsteady, aperiodic motion in which
all three velocity components fluctuate in space and
time.
• Every transported quantity shows similar fluctuations
(pressure, temperature, species, concentration, and Wake turbulence behind individual wind turbines Flow visualization over a spinning spheroid
so on) 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,
• Turbulent flows contains a wide range of eddy sizes permission must be sought for any other purpose. permission must be sought for any other purpose.

(scales):
• Large eddies derives their energy from the mean
flow. The size and velocity of large eddies are on
the order of the mean flow.
• Large eddies are unstable and they break-up into
smaller eddies.
• The smallest eddies convert kinetic energy into
thermal energy via viscous dissipation.
• The behavior of small eddies is more universal in
nature. Buoyant plume of smoke rising from a stick of incense 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
Photo credit: https://www.flickr.com/photos/jlhopgood/ the northern Pacific Ocean encountered Alaska's Aleutian Islands Tunnel
This work is licensed under a Creative Commons License Photo credit: USGS EROS Data Center Satellite Systems Branch. Photo credit: NASA Dryden Flow Visualization Facility.
(CC BY-NC-ND 2.0) 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,
823 permission must be sought for any other purpose. permission must be sought for any other purpose. 824

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence, does it matter?


Blower simulation using sliding grids

No turbulence model used (laminar, K-epsilon turbulence model


unresolved DNS, name it as you want) www.wolfdynamics.com/wiki/turb/turb2.gif
www.wolfdynamics.com/wiki/turb/turb1.gif
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 825 826
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence, does it matter? Turbulence, does it matter?


Vortex shedding past square cylinder Vortex shedding past square cylinder

Turbulence model Drag coefficient Strouhal number Computing time (s)

Laminar 2.81 0.179 93489

LES 2.32 0.124 77465

DES 2.08 0.124 70754


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 URANS (WF) 2.31 0.130 67830
www.wolfdynamics.com/wiki/squarecil/urans2.gif

URANS (No WF) 2.28 0.135 64492

RANS 2.20 - 28246 (10000 iter)

Experimental values 2.05-2.25 0.132 -

Note: all simulations were run using 4 cores.

References:
Laminar (no turbulence model) – Vortices DES (SpalartAllmarasDDES) – Vortices visualized by 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
visualized by Q-criterion Q-criterion cylinder. Report. SFB 210 /E/100.
www.wolfdynamics.com/wiki/squarecil/laminar.gif www.wolfdynamics.com/wiki/squarecil/des.gif 827 828

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence modeling in engineering Reynolds number and Rayleigh number


• Most natural and engineering flows are turbulent, hence the necessity of modeling turbulence. • It is well known that the Reynolds number characterizes if the flow is laminar or turbulent.
• The goal of turbulence modeling is to develop equations that predict the time averaged velocity, pressure, • So before doing a simulation or experiment, check if the flow is turbulent.
temperature fields without calculating the complete turbulent flow pattern as a function of time. • The Reynolds number is defined as follows,
• There is no universal turbulence model, hence you need to know the capabilities and limitations of the
Convective effects
turbulence models.
where
• Simulating turbulent flows in any general CFD solver requires selecting a turbulence model, providing initial
Viscous effects
conditions and boundary conditions for the closure equations of the turbulent model, selecting a near-wall
modeling, and choosing runtime parameters and numerics.
• Where U and L are representative velocity and length scales.
• If you are dealing with natural convection, you can use the Rayleigh number, Grashof number, and Prandtl
number to characterize the flow.
Why modeling turbulent flows is challenging? Specific heat Thermal expansion coefficient
• Unsteady aperiodic motion.
Buoyancy effects
• All fluid properties and transported quantities exhibit random spatial and temporal variations.
• They are intrinsically three-dimensional due to vortex stretching. Viscous effects Thermal conductivity
• Strong dependence from initial conditions.
• Contains a wide range of scales (eddies).
• Therefore, in order to accurately model/resolve turbulent flows, the simulations must be three-dimensional, Momentum diffusivity
time-accurate, and with fine enough meshes such that all spatial scales are resolved.
829
Thermal diffusivity 830
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Reynolds number and Rayleigh number What happens when we increase the Reynolds number?
• Turbulent flow occurs at large Reynolds number.
• For external flows, Creeping flow (no s eparation)
S teady flow Re < 5
Around slender/streamlined bodies (surfaces) • Easy to simulate
A pair of s table vortices
• Steady
in the wake
Around an obstacle (bluff body) S teady flow
5 < Re < 40 - 46
• Relative easy to
simulate.
• For internal flows, Laminar vortex s treet
(Von Karman s treet)
Uns teady flow
40 - 46 < Re < 150 • It becomes more
challenging when
the boundary layer
Laminar boundary layer up to
the s eparation point, turbulent
150 < Re < 300 transition to
Trans ition to turbulence
wake
Uns teady flow 300 < Re < 3 x 10 5 turbulent
• Notice that other factors such as free-stream turbulence, surface conditions, blowing, suction, • Unsteady
roughness and other disturbances, may cause transition to turbulence at lower Reynolds Boundary layer trans ition to 5 6
number. turbulent 3 x 10 < Re < 3 x 10
Uns teady flow • Challenging to
• If you are dealing with natural convection and buoyancy, turbulent flows occurs when simulate
Turbulent vortex s treet, but the
6 • Unsteady
wake is narrower than in the
laminar cas e 3 x 10 > Re
Uns teady flow

Vortex shedding behind a cylinder and Reynolds number


831 832

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Vorticity does not always mean turbulence Turbulence modeling – Fluctuations of transported quantities

Instantaneous vorticity magnitude field • We have defined turbulence as an unsteady, aperiodic motion in which velocity components and every
www.wolfdynamics.com/wiki/cylinder_vortex_shedding/movvort.gif
transported quantity fluctuate in space and time.
• For most engineering application it is impractical to account for all these instantaneous fluctuations.
• The Reynold number in this case is 100, for these conditions the flow still is laminar. • Therefore, we need to somehow remove those small scales by using models.
• We are in the presence of the Von Karman vortex street, which is the periodic shedding of vortices caused by • To remove the instantaneous fluctuations or small scales, two methods can be used: Reynolds averaging and
the unsteady separation of the fluid around blunt bodies. Filtering
• Vorticity is not a direct indication of turbulence. • Both methods introduce additional terms that must be modeled for closure.
• However turbulent flows are rotational, they exhibit vortical structures. 833 • We are going to talk about closure methods later. 834
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence modeling – Fluctuations of transported quantities Turbulence modeling – Fluctuations of transported quantities

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 Flow in a pipe. (a) Laminar, (b) Transitional, (c) Turbulent
is parabolic.
• Turbulence has a direct effect on the velocity profiles and mixing of transported quantities.
• 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,
• The turbulent case shows two regions. One thin region close to the walls with very large velocity this kind of mixing can take very long times.
gradients, and a region far from the wall where the velocity profile is nearly uniform. • Case (b) shows a transitional state where the dye streak becomes wavy but the main flow still is laminar.
• The thin region close to the walls has very large velocity gradients and is laminar. • Case (c) shows the turbulent state, where the dye streak changes direction erratically, and the dye has mixed
• Far from the flows, the flow becomes turbulent. 835 significantly with the main flow due to the velocity fluctuations. 836

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence near the wall - Law of the wall Turbulence near the wall - Law of the wall
Note: The scales are
aminar boundary ransition urbulent boundary exaggerated for clarity
layer region layer

oundary layer t i ness


integral s ales
u

ogarit mi layer

uffer layer
is ous sublayer inertial s ales
riti al lengt

Actual profile - Physical velocity profile dissi ation s ales


• Near walls, in the boundary layer, the velocity changes rapidly. Actual profile - Physical velocity profile
Non-dimensional profile
• A laminar boundary layer starts to form at the leading edge. As the flow proceeds further downstream, large shear stresses and
velocity gradient develop within the boundary layer. At one point, the flow becomes turbulent.
• In CFD, we try to avoid the transition layer (buffer layer). What is happening in this region is not well understood. The flow can
become laminar again or can become turbulent. • The use of the non-dimensional velocity u+ and non-dimensional distance from the wall y+, results in a
• The velocity profiles in the laminar and turbulent regions are different. predictable boundary layer profile for a wide range of flows.
• The turbulent motion increases the mixing. • Turbulence models require different considerations depending on whether you solve the viscous sublayer of
• Turbulence models require different considerations depending on whether you solve the viscous sublayer, model the log-law model the log-law layer.
layer, or solve the whole boundary layer. 837 838
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence near the wall - Law of the wall Near-wall treatment and wall functions
• When dealing with wall turbulence, we need to
choose a near-wall treatment.
• If you want to resolve the boundary layer up to the
viscous sub-layer you need very fine meshes close
to the wall.
• In terms of y+, you need to cluster at least 6 to 10
layers at y+ < 10.
• This is the most accurate approach, but it is
computationally expensive.

• When dealing with wall turbulence, we need to


Where y is the distance normal to the wall, U choose a near-wall treatment.
is the shear velocity, and relates the mean
velocity to the shear velocity • If you are not interested in resolving boundary layer
up to the viscous sub-layer, you can use wall
or wall distance units is a very functions.
important concept when dealing • In terms of y+, wall functions will model everything
with turbulence modeling, for y+ < 30
remember this definition as we are • This approach use coarser meshes, but you should
going to use it a lot. be aware of the limitations of the wall functions.

839 840

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence modeling – Grid scales Overview of turbulence modeling approaches

MODEL

Increasing modelling and mathematical


Cell size
This cell is resolving the eddies

Increasing computational cost


RANS
Reynolds-Averaged Navier-Stokes equations

URANS

complexity
Unsteady Reynolds-Averaged Navier-Stokes equations

To resolve the boundary layer


SAS
Scale Adaptive Simulations
you need very fine meshes
Scale-Resolving Simulations

Cell size
This cell is not resolving the eddies Cell size
This cell may be resolving the eddies DES
SRS

Detached Eddy Simulations


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.
LES
Large Eddy Simulations
• Therefore, if we want to capture all scales we need very fine meshes in the whole domain.

Bullet at Mach 1.5 DNS


Direct Numerical Simulations
Photo credit: Andrew Davidhazy. Rochester Institute of Technology.
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose. 841 842
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Overview of turbulence modeling approaches Short description of some RANS turbulence models

Model Short description


Suitable for external aerodynamics, tubomachinery and high-speed flows. Good for mildly
complex external/internal flows and boundary layer flows under pressure gradient (e.g. airfoils,
Spalart-Allmaras wings, airplane fuselages, ship hulls). Performs poorly for free shear flows and flows with strong
separation.
RANS LES (Instantaneous field)
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
RANS/URANS DES/LES DNS initial iterations, initial screening of alternative designs, and parametric studies.

• Solve the time-average NSE. • Solve the filtered unsteady NSE. • Solves the unsteady laminar NSE. 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
• All turbulent spatial scales are • Sub-grid scales (SGS) are filtered, • Solves all spatial and temporal Realizable k–epsilon behind bluff bodies, stall in wide-angle diffusers, room ventilation). It overcome the limitations of
modeled. grid scales (GS) are resolved. scales; hence, requires extremely the standard k-epsilon model.
fine meshes and small time-steps.
• Many models are available. One • Aim at resolving the temporal scales,
equation models, two equation hence requires small time-steps. • No modeling is required. Superior performance for wall-bounded boundary layer, free shear, and low Reynolds number
models, Reynolds stress models,
• For most industrial applications, it is • It is extremely computational Standard k–omega flows compared to models from the k-epsilon family. Suitable for complex boundary layer flows
transition models, and so on. under adverse pressure gradient and separation (external aerodynamics and turbomachinery).
computational expensive. However, expensive.
• This is the most widely approach for thanks to the current advances in
• Not practical for industrial flows.
industrial flows. parallel and scientific computing it is Offers similar benefits as standard k–omega. Not overly sensitive to inlet boundary conditions
becoming affordable. • It is intrinsically 3D and asymmetric. SST k–omega like the standard k–omega. Provides more accurate prediction of flow separation than other
• Unsteady RANS (URANS), use the
same equations as the RANS but • Many models are available. RANS models. Probably the most widely used RANS model.
with the transient term retained.
• It is intrinsically 3D and asymmetric.
• It can be used in 2D and 3D cases. 843 844

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence modeling – Starting equations Incompressible RANS equations


• The RANS equations are similar to the laminar NSE (no turbulence model).
• The main difference is that all quantities are averaged (the overbar over the field
quantities) and the appearance of a new term named Reynolds stress tensor.
NSE
Reynolds stress tensor

Additional closure equations for the turbulence models

If we retain this term, we talk about URANS equations and if we drop it we talk about RANS equations

• Equations cannot be derived from fundamental principles.


• All turbulence models contain some sort of empiricism. • To derive the RANS equations we used Reynolds decomposition and a few averaging
rules (a lot of algebra is involved),
• Some calibration to observed physical solutions is contained in the turbulence
models.
• Also, some intelligent guessing is used.
• A lot of uncertainty is involved! 845 846
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Incompressible RANS equations Incompressible RANS equations


• The RANS approach to turbulence modeling requires the Reynolds stresses to be appropriately modeled. • 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.
• The Reynolds stress tensor can be modeled using the Boussinesq hypothesis, Reynolds stress models, non- • Besides RANS, there is also LES and DES turbulence models.
linear eddy viscosity models or algebraic models. • The idea behind LES/DES models is very similar to RANS, but instead of using
• Let us address the Boussinesq hypothesis which is the most widely used approach to model the Reynolds
averaging we filter the equations in space, and we solve the temporal scales
stress tensor.
• By using this hypothesis we can relate the Reynolds stress tensor to the mean velocity gradient such that, • 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;
• In the previous equation, denotes the strain-rate tensor. therefore, need to be modelled.
• is the identity matrix. • LES/DES models are intrinsically unsteady and three-dimensional.
• is the turbulent eddy viscosity.
• Let us take a look at the governing equations of the RANS model.
• is the turbulent eddy viscosity.
• At the end of the day we want to determine the turbulent eddy viscosity. • Remember, the main goal of the RANS turbulence models is to compute the
• The turbulent eddy viscosity is not a fluid property, it is a property needed by the turbulence model. Reynolds stress tensor and the turbulent eddy viscosity.
• And each model will compute this quantity in a different way.
847 848

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence model overview Turbulence model free stream initial conditions

• It is called because it solves two additional equations for modeling the • The initial value for the turbulent kinetic energy can be found as follows
turbulence, namely, the turbulent kinetic energy and the specific kinetic energy

• The initial value for the specific kinetic energy can be found as follows

• Where is the viscosity ratio and is the turbulence intensity.


• These are the closure equations of the turbulence problem using Reynolds average.
• If you are totally lost, you can use these reference values. They work most of the
• These are not physical quantities. They kind of represent the generation and
times, but it is a good idea to have some experimental data or a better initial estimate.
destruction of turbulence.
• In the model, the turbulent eddy viscosity can be computed as follows, Low Medium High

I 1.0 % 5.0 % 10.0 %

1 10 100
• It is worth mentioning that different turbulence models will have different ways of
computing the turbulent eddy viscosity. 849 • By the way, use these guidelines for external aerodynamics only. 850
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence model boundary conditions at the walls Turbulence model boundary conditions at the walls
• Remember, you can only use wall functions if the base patch (the patch type
• Follow these guidelines to find the boundary conditions for the near-wall treatment. defined in the boundary dictionary), is of type wall.
• We highly recommend you to read the source code and find the references used to
implement the model. Field Wall functions – High RE Resolved BL – Low RE

• As for the free-stream boundary conditions, you need to give the boundary conditions nut(–)WallFunction* or
nutUSpaldingWallFunction** or
nut nutLowReWallFunction or
for the near-wall treatment. nutUSpaldingWallFunction**
fixedValue 0 (or a small number)
• When it comes to near-wall treatment, you have three options:
k, q, R kqRWallFunction fixedValue 0 (or a small number)
• Use wall functions:
zeroGradient or fixedValue 0
epsilon epsilonWallFunction
(or a small number)
• Use scalable wall functions, this only applies with the model:
omegaWallFunction** or
omega omegaWallFunction
fixedValue (with a large number)
• Resolve the boundary layer (no wall functions):
nuTilda – fixedValue 0 (or a small number)

* $WM_PROJECT_DIR/src/TurbulenceModels/turbulenceModels/derivedFvPatchFields/wallFunctions/nutWallFunctions
851 ** For scalable wall functions 852

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence models available in OpenFOAM® wall distance units normal to the wall
• There are many turbulence models implemented in OpenFOAM®, from RANS to LES. • We never know a priori the value (because we do not know the friction velocity).
• You can also implement yours!
• What we usually do is to run the simulation for a few time-steps or iterations, and then
• You can find the turbulence models in the following directories: we get an estimate of the value.
• $WM_PROJECT_DIR/src/TurbulenceModels
• After determining where we are in the boundary layer (viscous sub-layer, buffer layer
• The wall functions are in the following directories: or log-law layer), we take the mesh as a good one or we modify it if is deemed
• $WM_PROJECT_DIR/src/TurbulenceModels/turbulenceModels/derivedFvPatc necessary.
hFields
• It is an iterative process and it can be very time consuming, as it might require
• If you have absolutely no idea of what model to use, we highly recommend you the k-omega remeshing and rerunning the simulation.
family models or the realizable k-epsilon model.
• Remember, when a turbulent flow enters a domain, turbulent boundary conditions and initial • Have in mind that it is quite difficult to get a uniform value at the walls.
conditions must be specified.
• Try to get a mean value as close as possible to your target.
• Also, if you are dealing with wall bounded turbulence you will need to choose the near-wall
treatment. • Also, check that you do not get very high maximum values of (more than a 1000)
• You can choose to solve the viscous sub-layer (low-Re approach) or use wall functions • Values up to 300 are fine. Values larger that 300 and up to a 1000 are acceptable is
(high-Re approach). they do not covert a large surface (no more than 10% of the total wall area), or they
• You will need to give the appropriate boundary conditions to the near-wall treatment. are not located in critical zones.
• Our task is to choose the less wrong model ! 853 • Use common sense when accessing value. 854
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Estimating normal wall distance Wall distance units and some rough estimates
• To get an initial estimate of the distance from the wall to the first cell center ,
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.
• Similar to , the wall distance units can be computed in the stream-wise ( ) and span-
4. wise ( ) directions.
• DES and RANS simulations do not have stream-wise and span-wise wall distance units
Your desired value requirements as in LES simulations. Therefore, they are more affordable.
5.
• Typical requirements for LES are:

• You will find a simple calculator for the wall distance estimation in the following link:
http://www.wolfdynamics.com/tools.html?id=2
855 856

A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®

Turbulence modeling guidelines and tips Turbulence modeling guidelines and tips
• Compute Reynolds number and determine whether the flow is turbulent. • Always monitor the turbulent variables, some of them are positive bounded.
• Try to avoid the use of turbulent models with laminar flows. • Avoid strong oscillations of the turbulent variables.
• Choose the near-wall treatment and estimate before generating the mesh. • If you are doing LES, remember that these models are intrinsically 3D and unsteady.
• Run the simulation for a few time steps and get a better prediction of and You should choose your time-step in such a way to get a CFL of less than 1 and
correct your initial prediction of . preferably of about 0.5.

• The realizable or models are good choices for general • If you are doing RANS with wall functions, it is perfectly fine to use upwind to
applications. discretize the turbulence closure equations. After all, turbulence is a dissipative
process. However, some authors may disagree with this, make your own conclusions.
• The standard model is very reliable, you can use it to get initial values.
• On the other hand, if you are using a wall resolved approach, it is better to use a high-
• If you are interested in resolving the large eddies and modeling the smallest eddies, order discretization scheme to discretize the turbulence closure equations.
DES or LES are the right choice.
• If you are doing unsteady simulations, always remember to compute the average
• If you do not have any restriction in the near wall treatment method, use wall values (ensemble average).
functions (even with LES/DES models).
• If you are dealing with external aerodynamics and detached flows, DES simulations
• Be aware of the limitations of the turbulence model chosen, find and read the original are really affordable.
references used to implement the model in OpenFOAM®.
• The work-horse of turbulence modeling in CFD: RANS
• Set reasonable boundary and initial conditions for the turbulence model variables.
857 858
A crash introduction to turbulence modeling in OpenFOAM® Turbulence modeling hands-on tutorials
References
• Turbulent Flows
• Laminar-Turbulent flat plate
Stephen B. Pope • Let us run this case. Go to the directory:
• Turbulence Modeling for CFD
David C. Wilcox
• Turbulence: An Introduction for Scientists and Engineers $PTOFC/advanced_physics/turbulence/flatPlate
P. A. Davidson
• Large Eddy Simulation for Incompressible Flows
Pierre Sagaut
• A First Course in Turbulence
H. Tennekes and J. L. Lumley • 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.
• Boundary-Layer Theory
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
H. Schlichting run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
• https://turbmodels.larc.nasa.gov/ 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.
859 860

Turbulence modeling hands-on tutorials Turbulence modeling hands-on tutorials


Laminar-Turbulent flat plate 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.
• Then, you can compute the shear velocity, friction coefficient, and u+ and y+ values.

• 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. 861 862
Turbulence modeling hands-on tutorials Turbulence modeling hands-on tutorials
Laminar-Turbulent flat plate
• We are going to use the following solver: simpleFoam (for RANS). • Vortex shedding past square cylinder
• This case is rather simple but we will use it to explain many features used in • Let us run this case. Go to the directory:
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).
$PTOFC/advanced_physics/turbulence/squarecil
• 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. • In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
• It is also a good idea to setup a few functionObjects, such as: y+, minimum and how to run the case. In this file, you might also find some additional comments.
maximum values, forces, time average, and online sampling. • 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
• You will find the instructions of how to run this case in the file README.FIRST automatically by typing in the terminal, for example, sh run_solver.
located in the case directory. • 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.
863 864

Turbulence modeling hands-on tutorials Turbulence modeling hands-on tutorials


Vortex shedding past square cylinder Vortex shedding past square cylinder

Turbulence model Drag coefficient Strouhal number Computing time (s)


Physical and numerical side of the
Laminar 2.81 0.179 93489
problem:
• The governing equations of the problem are the LES 2.36 0.124 77465
incompressible Navier-Stokes equations.
• To model the turbulence, we will use two approaches, DES 2.08 0.124 70754
LES and RANS.
SAS 2.40 0.164 57690
• We are going to work in a 3D domain with periodic
boundary conditions.
URANS (WF) 2.31 0.130 67830
• This problem has plenty of experimental data for
validation. URANS (No WF) 2.29 0.135 64492

RANS 2.30 - 28246 (10000 iter)

Experimental values 2.05-2.25 0.132 -

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.
Working fluid: Water 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.
865 866
Turbulence modeling hands-on tutorials Turbulence modeling hands-on tutorials
Vortex shedding past square cylinder Vortex shedding past square cylinder

• We will use this case to learn how to setup a turbulent case (RANS and LES). • We select the turbulence model in the turbulenceProperties dictionary file.

• To run this case we will use the solvers simpleFoam (steady solver) and pimpleFoam • This dictionary file is located in the directory constant.
(unsteady solver). • To select the K-Omega SST turbulence model,
• To get fast outcomes, we will use a coarse mesh. But feel free to refine the mesh, specially
close to the walls.
17 simulationType RAS; RANS type simulation
• Remember, as we are introducing new closure equations for the turbulence problem, we need to 18
define initial and boundary conditions for the new variables. 19 RAS RANS sub-dictionary
20 {
• We will use a few functionObjects to compute some additional quantities, such as, Q criterion, 21 RASModel kOmegaSST; RANS model to use

y+, minimum and maximum values, forces, time average, and online sampling.
22 turbulence on; Turn on/off turbulence. Runtime modifiable
• After finding the solution, we will visualize the results.
23 printCoeffs on; Print coefficients at the beginning
• We will also compare the numerical solution with the experimental results. 24 }

• 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 • Remember, you need to assign boundary and initial conditions to the new variables (k, omega,
case directory. and nut).

867 868

Turbulence modeling hands-on tutorials Turbulence modeling hands-on tutorials


Vortex shedding past square cylinder Vortex shedding past square cylinder
• We select the turbulence model in the turbulenceProperties dictionary file. • To select wall functions, follow this table,
• This dictionary file is located in the directory constant.
• To select the LES (Smagorinsky) turbulence model,
Field Wall functions – High RE Resolved BL – Low RE

17 simulationType LES; LES type simulation


18 nut nutUSpaldingWallFunction fixedValue 0 or a small number
19 LES LES sub-dictionary
20 {
21 LESModel Smagorinsky; LES model to use k kqRWallFunction fixedValue 0 or a small number

24 turbulence on; Turn on/off turbulence. Runtime modifiable


omega omegaWallFunction omegaWallFunction
25 printCoeffs on; Print coefficients at the beginning

27 delta cubeRootVol;
31 cubeRootVolCoeffs
32 {
LES filter • In this tutorial,
33 deltaCoeff 1; • Use High RE for RANS.
34 }
100 } • Use High RE and Low RE for URANS.
• Use High RE and Low RE for LES.
• Remember, you need to assign boundary and initial conditions to the new variables (nut).
869 870
Turbulence modeling hands-on tutorials Roadmap
Vortex shedding past square cylinder
• The initial value for the turbulent kinetic energy can be found as follows,
A crash introduction to:
1. Turbulence modeling in OpenFOAM®
• The initial value for the specific kinetic energy can be found as follows, 2. Multiphase flows modeling in
OpenFOAM®
3. Compressible flows in OpenFOAM®
• Use the following initial estimates, and 4. Moving bodies in OpenFOAM®
5. Source terms in OpenFOAM®
• At this point, we are ready to run. But before running, remember to setup the right
numerics in the dictionary files fvSolution and fvSchemes. 6. Scalar transport pluggable solver
• Also, for the LES simulation try to keep the CFL number below 0.9
• Finally, do not forget to setup the functionObjects to compute the forces, do the
sampling, and compute y+ on-the-fly.
871 872

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

What is a multiphase flow? Examples of multiphase flows


• A multiphase flow is a fluid flow consisting of more than one phase component and
have some level of phase separation above molecular level.
• Multiphase flows exist in many different forms. For example, two phase flows can be
classified according to the state of the different phases:
• Gas-Liquid mixture.
• Gas-Solid mixture.
• Liquid-Solid mixture. Municipal and industrial water treatment Cargo ship wake
http://www.asiapacific.basf.com/apex/AP/en/upload/Press2010/BASF-Water-Chem-2010-Paper- http://developeconomies.com/development-economics/how-to-get-america-back-on-track-free-trade-edition/

• Immiscible liquid-liquid.
Chem-2010-Intex-Shanghai

• Multiphase flows are present in many industrial processes and natural systems.
• Hence the importance of understanding, modeling, and simulating multiphase flows.

Propeller cavitation
http://www.veempropellers.com/features/cavitationresistance
Siltation & Sedimentation
http://blackwarriorriver.org/siltation-sedimentation/

873 874
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Examples of multiphase flows Why simulating multiphase flows is challenging?


• Simulating multiphase flows is not an easy task.
• The complex nature of multiphase flows is due to:
• More than one working fluid.
• The transient nature of the flows.
• The existence of dynamically changing interfaces.
Cooling Towers
• Significant discontinuities (fluid properties and fluid separation).
https://whatiswatertreatment.wordpress.com/what-are-the-systems-associated-with-water-
Volcano eruption

• Complicated flow field near the interface.


http://americanpreppersnetwork.com/2014/08/preparing-volcano-eruption.html
treatment-and-how-are-they-treated/103-2/

• Interaction of small scale structures (bubbles and particles).


• Different spatial-temporal scales.
• Dispersed phases and particle-particle interactions.
• Mass transfer and phase change.
• Turbulence.
• Many models involved (drag, lift, heat transfer, turbulence dispersion,
Fermentation of beer and spirits
http://www.distillingliquor.com/2015/02/05/how-to-make-alcohol-and-spirits/
Chemical reactor for the pharmaceutical and
biotechnology industry frictional stresses, collisions, kinetic theory, and so on).
http://www.total-mechanical.com/Industrial/CaseStudies.aspx
875 876

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Classifying multiphase flows according to phase morphology How to treat the wide range of behaviors in multiphase flows

• Disperse system: the phase is dispersed as non-contiguous isolated


• Fully resolved: solves complete Increase
regions within the other phase (the continuous phase) . When we work with a
physics. All spatial and temporal scales
disperse phase we say that the system is dispersed: disperse-continuous
are resolved. Equivalent to DNS in
flow.

Modeling requirements
turbulence modelling.

Computational power
• Separated system: the phase is contiguous throughout the domain and
• Eulerian-Lagrangian: solves idealized
there is one well defined interphase with the other phase. When we work
isolated particles that are transported
with continuous phases we say that the system is separated: continuous-
with the flow. One- or two-way coupling
continuous flow.
is possible. Can account for turbulence,
momentum transfer, and mass transfer.
• Eulerian-eulerian: solves two or more
co-existing fluids. The system can be
dispersed or separated, and can account
for turbulence, momentum transfer, and
Increase
Dispersed system Separated system
mass transfer.
877 878
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

How to treat the wide range of behaviors in multiphase flows How to treat the wide range of behaviors in multiphase flows

Separated system Dispersed system

VOF ≈ 0.5
Average phase
properties

• Dispersed phase in a continuous phase.

Eulerian-Eulerian approach • In this case, the VOF method is not able to handle
Eulerian-Eulerian approach Eulerian-Lagragian approach bubbles smaller than grid scales.
(Multi-fluid and mixture
(VOF) (Particle tracking)
models)
• Multi-fluid and mixture models are able to model • Multi-fluid and mixture approaches can model
bubbles smaller than grid scales by averaging the bubble coalescence, bubble break-up and
phase properties in the discrete domain. wake entrainment in dispersed systems.

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.
879 880

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

How to treat the wide range of behaviors in multiphase flows How to treat the wide range of behaviors in multiphase flows

• When using multi-fluid and mixture


approaches, interfacial momentum
The particles position is
transfer models must be taken into
tracked by solving an ODE
account in order to model mass
for each particle
transfer and phases interaction.
The continuous phase is
• As for turbulence modeling, there is solved in the mesh
no universal model.

• It is up to you to choose the model


that best fit the problem you are
solving.

• Depending on the physics involved,


you will find different models and
formulations
• In the Eulerian-Lagrangian framework, the continuous phase is solved in an Eulerian reference
system and the particles or dispersed phase is solved in a Lagrangian reference system.
• You need to know the applicability and • The particles can be smaller or larger than the grid size.
limitations of each model, for this,
refer to the literature. • The particles can be transported passively, or they can be coupled with the fluid governing
equations.
• It accounts for particle interaction and mass transfer.
881
• The particles can interact with the boundaries and have a fate. 882
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Multiphase flows – Grid scales


Numerical approaches for multiphase flows
Free surface (system scale)
• Applicability of the VOF method to separated
systems (non-interpenetrating continua). Eulerian-Eulerian Eulerian-Eulerian
• In the figure, the free surface and large
Eulerian-Lagrangian
bubbles can be track/resolve by the mesh.
(VOF) (Dispersed systems)
• The smaller the features we want to
track/resolve, the smaller the cells should be.
• Bubbles, droplets and/or particles larger than
Medium bubbles grid scales (GS), can be resolved using VOF.
• Non-interpenetrating • Interpenetrating continua. • Continuous phase:
Large bubbles
(system-scales) continua. Eulerian.
(system scale)
• To resolve a bubble you will need at least two • Continuous phase:
cells in every direction • Continuous phases: Eulerian. • Dispersed phase:
• Bubbles, droplets and/or particles smaller Eulerian. Lagrangian.
than grid scales (sub-grid scales or SGS), can
• Dispersed phase: Eulerian.
not be resolve using the VOF method. • Fluid properties are written • Phase-weighted averages. • Solves ODEs for particle
Bubble break-up • In such a case, we need to use models. on either side of the tracking (for every single
and coalescence interface (no averaging). • Solves PDEs for all phases particle).
Small bubbles interaction and (meso-scales) • Also, bubble break-up, coalescence and
(including interphase
motion of small particles entrainment must be modeled, unless the • Solves one single set of • Solves a set of PDEs for
(micro-scales) mesh is fine enough so it captures the transfer terms): mass,
PDEs: mass, momentum, the continuous phase:
dynamics and solves the smallest scales. momentum, energy.
energy. mass, momentum, energy.
• It can deal with gas-liquid,
• Phase interaction terms
Multiphase flows are
gas-solid, and liquid-solid
(including interphase
transient and multiscale interactions.
transfer terms).
883 884
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose.

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Numerical approaches for multiphase flows Numerical approaches for multiphase flows

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
• Simulations showing free surface tracking using the VOF approach
entrainment using the VOF method.
• The left image corresponds to a simulation with rigid body motion and accurate surface tracking using the VOF
• In this simulation the free surface and bubbles are capture by using AMR. However, the smallest bubble that
method.
can be resolved is at the smallest grid size. 885 886
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Numerical approaches for multiphase flows Numerical approaches for multiphase flows

twoPhaseEulerFoam twoPhaseEulerFoam
http://www.wolfdynamics.com/training/mphase/image18.gif
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

• Eulerian-Eulerian simulation (gas-liquid).


• The bubbles are not being solved, instead, the interaction between phase is being averaged.
• Eulerian-Eulerian simulations using the Eulerian-Granular KTGF approach (solid-gas).
• The granular phase is simulated as continuous phase.
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. • In these simulations we can observe the influence of turbulence modeling in the solution.
Chemical Engineering Science 57 (2002) 4715 – 4736 887 888

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Numerical approaches for multiphase flows Volume-of-Fluid (VOF) governing equations for separated systems

• The incompressible, isothermal governing equations can be written as


follows, Source terms:
• Porous media
• Coriolis forces
• Centrifugal forces
Surface tension - Continuum surface force (CSF) • Mass transfer
• and so on …

DPMFoam twoPhaseEulerFoam
Particle-particle interactions colored by velocity Air volume fraction
Phase transport equation and interface
magnitude (particles not to scale) Turbulent case tracking with surface compression
http://www.wolfdynamics.com/training/mphase/image43.gif http://www.wolfdynamics.com/training/mphase/image42.gif

• Comparison of an Eulerian-Lagrangian simulation and an Eulerian-Eulerian simulation (gas-solid).


Volume fraction (bounded quantity)
• In the Eulerian-Lagrangian approach we track the position of every single particle. We also solve the fate and
interaction of all particles.
• In the Eulerian-Eulerian approach we solve the granular phase as a continuous phase.
• The computational requirements of the Eulerian-Eulerian simulation are much lower than those for the
• You can see the volume fraction as a pointer that indicates what phase (with the
Eulerian-Lagrangian simulation. 889 corresponding physical properties), is inside each cell of the computational domain. 890
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Volume-of-Fluid (VOF) governing equations for separated systems Eulerian-Eulerian governing equations for dispersed systems
• The Eulerian-Eulerian approach solves the governing equations for each phase, it
• For example, in the case of two phases treats the phases as interpenetrating continua.
where phase 1 is represented by and
0 0 0 0.1 0.3 • The incompressible, isothermal governing equations with interface tracking can be
phase 2 is represented by ; a volume
written as follows,
fraction value of 1 indicates that the cell is fill 0 0 0.3 0.8 1 Surface tension - Continuum surface force (CSF)
with phase 1; a volume fraction of 0.8
indicates that the cell contains 80% of a 0 0.1 0.8 1 1 Interface forces or momentum transfer.
Bubbles interaction models
phase 1; and a volume fraction of 0, indicates
that the cell is fill with phase 2. 0 0.4 1 1 1
• The values between 0 and 1 can be seen as
Interface
the interface between the phases.

• The fluid properties can be written on either side of the interface as follows,
Source terms:
• Porous media
• Coriolis forces
• Centrifugal forces
• Mass transfer
• and so on …

891 892

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Eulerian-Lagrangian governing equations On the multiphase flows models


• In the Eulerian-Lagrangian framework, the continuous phase is solved in an Eulerian
reference system and the particles or dispersed phase is solved in a Lagrangian
reference system. • In OpenFOAM®, there are many interfacial momentum transfer
• The particles can be transported passively, or they can be coupled with the fluid models implemented.
governing equations (they can modify the fluid field).
• There are also many models for Eulerian-Lagrangian methods.
• The particles can interact with the boundaries, they can escape, bounce, stick, or
form a wall film. • No need to say that turbulence also applies to multiphase flows.
• This formulation accounts for particle interaction and mass transfer.
• The governing equations can be written as follows, • We want to remind you that there is no universal model, it is up
to you to choose the model that best fit the problem you are
solving.
• You need to know the applicability and limitations of each
model, for this, refer to the literature.
• Remember, you have the source code so feel free to explore it.
Any of the Eulerian formulations (single or multi-phase)
893 894
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Multiphase solvers in OpenFOAM® Multiphase solvers in OpenFOAM®


• OpenFOAM® comes with many solvers and models that can address a wide physics. • These are the multiphase solvers that you will use most of the time in
• When dealing with multiphase flows in OpenFOAM®, you can use VOF, Eulerian- OpenFOAM®.
Eulerian, Eulerian-Eulerian with VOF, and Eulerian-Lagrangian methods.
• The solution methods can account for turbulence models, interface momentum • The VOF approach:
transfer models, mass transfer models, particle interaction models and so on.
• interFoam family solvers
• It is also possible to add source terms, deal with moving bodies or use adaptive mesh
refinement.
• The Eulerian-Eulerian approach:
• twoPhaseEulerFoam, multiphaseEulerFoam
• You will find the source code of all the multiphase solvers in the directory:
• OpenFOAM-6/applications/solvers/multiphase
• The Eulerian-Granular KTGF (kinetic theory of granular flows) approach.
• twoPhaseEulerFoam
• You will find the source code all the particle tracking solvers in the directory:
• OpenFOAM-6/applications/solvers/lagrangian • The Eulerian-Lagrangian framework,
• DPMFoam, MPPICFoam
895 896

A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Multiphase solvers in OpenFOAM® Selecting physical properties and advanced physics


• In the directory constant you will find the dictionaries used to select physical
• Remember, you should always conduct production runs using a second properties and advanced physics.
order discretization scheme.
• The following dictionaries are compulsory:
• Most of multiphase flows are transient, so you need to use transient
methods. • g: in this dictionary you set the gravity field.

• You also need to add new entries in the dictionaries fvScheme and • transportProperties: in this dictionary you set the transport properties for
fvSolution. each phase.

• The new entries, correspond to the new terms and equations used by the • turbulenceProperties: in this dictionary you set the turbulence model.
solver. • The dictionary transportProperties requires special attention, as it is in this
• You also need to set the initial and boundary conditions and assign the dictionary where we set the transport properties for each phase.
physical properties. • We also give a name to the phases in the dictionary transportProperties.
• Hereafter we will only address how to select physical properties for the VOF • These dictionaries are standard for the VOF solvers (interFoam and so on).
method. However, the procedure is similar for other solvers.
• If you are using a different solver (e.g., twoPhaseEulerFoam), you will need to use
• In the training material, you will find many tutorials addressing the different additional dictionaries where you define the interfacial models and so on.
approaches.
897 898
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®

Selecting physical properties and advanced physics Selecting physical properties and advanced physics
• If you are using the solver interFoam, the transportProperties • In the directory 0 you will find the dictionaries used to define the boundary
dictionary should looks like this one: conditions and initial conditions of all field variables (including the volume
The first phase is always considered the primary phase
fraction)
Phases naming convention.
The name of the phases is chosen by phases (phase1 phase2);
the user.

phase1 properties phase1 • When you create the dictionaries for the boundary conditions and initials
{ conditions for the volume fraction (or alpha), you use the same naming
transportModel Newtonian; convention as in the dictionary transportProperties.
nu nu [ 0 2 -1 0 0 0 0 ] 1e-06;
rho rho [ 1 -3 0 0 0 0 0 ] 1000;
}
• That is to say, if you are naming you primary phase phase1, you should
phase2 properties phase2
{ create the dictionary alpha.phase1.
transportModel Newtonian;
nu nu [ 0 2 -1 0 0 0 0 ] 1.48e-05;
rho rho [ 1 -3 0 0 0 0 0 ] 1;
}
• This dictionary will contain the initial and boundary conditions of the volume
fraction
Surface tension between phase1
and phase2
sigma sigma [ 1 0 -2 0 0 0 0 ] 0.07;

899 900

A crash introduction to multiphase flows modeling OpenFOAM® Multiphase flows hands-on tutorials
Some useful bibliographical references
• Computational Techniques for Multiphase Flows • Free surface – Ship resistance simulation
G. H. Yeoh, J. Tu. 2009, Butterworth-Heinemann
• Multiphase Flow Analysis Using Population Balance Modeling: Bubbles, Drops and Particles • Let us run this case. Go to the directory:
G. H. Yeoh, C. P Cheung, J. Tu. 2013, Butterworth-Heinemann
• Turbulence Modeling for CFD
D. Wilcox. 2006, DCW Industries.
$PTOFC/advanced_physics/multiphase/wigleyHull
• Error analysis and estimation in the Finite Volume method with applications to fluid flows.
H. Jasak. PhD Thesis. 1996. Imperial College, London.
• Computational fluid dynamics of dispersed two-phase flows at high phase fractions
H. Rusche. PhD Thesis. 2002. Imperial College, London.
• Towards the numerical simulation of multi-scale two-phase flows
H. Marschall. PhD Thesis. 2011. Technische Universität München. • In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
• Derivation, Implementation, and Validation of Computer Simulation Models for Gas-Solid Fluidized how to run the case. In this file, you might also find some additional comments.
Bed • You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
B. van Wachem. PhD Thesis. 2000, TUDelft. run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case
• Gas-Particle flow in a vertical pipe with particle-particle intractions automatically by typing in the terminal, for example, sh run_solver.
J. L. Sinclair, R. Jackson AIChE Journal. Volume 35, Issue 9, 1473-1486, September 1989 • 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.
901 902
Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation Free surface – Ship resistance simulation

Water level – Height (m)

Drag coefficient
Hull position Time (s)

Comparison of water level on hull surface


Drag coefficient monitor

Free surface colored by height


http://www.wolfdynamics.com/training/mphase/image45.gif 903 904

Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials


Free surface – Ship resistance simulation Free surface – Ship resistance simulation

• We are going to use the following solver: interFoam • The next step is to set the boundary conditions and initial conditions.
• The first step is to set the physical properties. • In the dictionary constant/transportProperties we defined the phases water
• Go to the directory constant and open the dictionary transportProperties. and air, where water is the primary phase.
• Therefore, in the directory 0 we define the dictionary alpha.water that will take
The first phase is always considered the primary phase
the values of the phase water.
Phases naming convention.
The name of the phases is chosen by phases (water air);
• In this case, you will find the directory 0_org, here is where we keep a backup of the
the user.
original files as we are doing field initialization using setFields.
water properties water
{ • In the directory 0, you will find the dictionary p_rgh, in this dictionary we set the
transportModel Newtonian;
nu nu [ 0 2 -1 0 0 0 0 ] 1.09e-06; boundary and initial conditions for the pressure field, and the dimensions are in
rho rho [ 1 -3 0 0 0 0 0 ] 998.8; Pascals.
}
• The turbulence variables values were calculated using an eddy viscosity ratio equal
air properties air
{ to 1, turbulence intensity equal 5%, and the water properties.
transportModel Newtonian;
nu nu [ 0 2 -1 0 0 0 0 ] 1.48e-05; • If you are simulating numerical towing tanks, the setup of the boundary conditions is
rho rho [ 1 -3 0 0 0 0 0 ] 1; always the same.
}

Surface tension between phase1


• Feel free to reuse this setup.
sigma sigma [ 1 0 -2 0 0 0 0 ] 0.07;
and phase2

905 906
Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation Free surface – Ship resistance simulation
Opening
Air phase Wall Patch name Pressure Velocity Turbulence fields alpha.water

fixedValue
inflow fixedFluxPressure fixedValue fixedValue
calculated (nut)
Inlet outlet
inletOutlet
outflow inletOutlet outletPhaseMeanVelocity variableHeightFlowRate
calculated (nut)

Water phase Slip bottom symmetry symmetry symmetry symmetry

midplane symmetry symmetry symmetry symmetry

side symmetry symmetry symmetry symmetry

Note:
inletOutlet
Phases must be initialized top totalPressure pressureInletOutletVelocity
calculated (nut)
inletOutlet
on the internal cells and
boundary faces kqRWallFunction (k)
ship fixedFluxPressure fixedValue omegaFunction (omega) zeroGradient
nutkWallFunction (nut)
Symmetry
Physical domain and boundary patches 907 Typical setup of boundary conditions for numerical towing tank simulations 908

Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials


Free surface – Ship resistance simulation Free surface – Ship resistance simulation

• OpenFOAM® solves the following modified volume fraction convective • MULES options in the fvSolution dictionary.
equation to track the interface between the phases, • 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.

(phi, alpha) (phirb, alpha) nAlphaCorr 3; Number of corrections.


Use a TVD scheme with gradient limiters. Use a high order scheme. The use of linear Use 2-3 for slowly varying flows.
Good choice is the vanLeer scheme. interpolation is fine for this term. Use 3 or more for highly transient, high Reynolds,
high CFL number flows.

nLimiterIter 10; Number of iterations to calculate the MULES


• Where a value of (cAlpha), is recommended to accurately resolve limiter. Use 3-5 if CFL number is less than 3. Use
the sharp interface. 5-10 if CFL number is more than 3.

• To solve this equation, OpenFOAM® uses the semi-implicit MULES method. alphaApplyPrevCorr yes; Use previous time corrector as initial estimate.
… Set to yes for slowly varying flows. Set to no for
highly transient flows.
• The MULES options can be controlled in the fvSolution dictionary. 909
} 910
Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation Free surface – Ship resistance simulation

• Additional notes on the fvSolution dictionary. • 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
Set to yes for high Reynolds flows, where
momentumPredictor yes; convection dominates governing equations.
Recommended value is 1 (equivalent to PISO). • Convective terms discretization is set as follows:
nOuterCorrectors 1; Increase to improve the stability of second
order time discretization schemes (LES
simulations).
divSchemes

These terms are related to the


Increase for highly coupled problems.
Recommended to use at least 2 correctors. {

volume fraction equation


nCorrector 3; It improves accuracy and stability. div(rhoPhi,U) Gauss linearUpwind grad(U);
Recommend to use at least 1 corrector. div(phi,alpha) Gauss vanLeer;
nNonOrthogonalCorrectors 2;
Increase the value for bad quality meshes. div(phirb,alpha) Gauss linear;
div((muEff*dev(T(grad(U))))) Gauss linear;
}

• 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. • Notice that we are using a high resolution scheme for the surface tracking or
911
div(phi,alpha). 912

Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials


Free surface – Ship resistance simulation Free surface – Ship resistance simulation

• For time discretization we can use an unsteady formulation (Euler in this case). • A way to accelerate the convergence to steady state, is by using local time stepping.
• This scheme requires setting the time-step, and it should be choosing in such a way • In LTS or local time steeping, the time-step is manipulated for each individual cell in
that it resolves the mean physics. the mesh, making it as high as possible to enable the simulation to reach steady-
• Remember, as the free surface is a strong discontinuity, for stability and good state quickly.
resolution we need to use a CFL less than one for the interface courant. • 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.
ddtSchemes
• 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.
default Euler;
} • To enable LTS, we use the localEuler method.

ddtSchemes
• Hereafter, we are using what is know as global time stepping, that is, the CFL {
number is limited by the smallest cell. default localEuler;
• The simulation is time-accurate, but it requires a lot of CPU time to reach a steady }
state (if it reaches one).
913 914
Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation Free surface – Ship resistance simulation

• In the LTS method, the maximum flow CFL number, maximum interface CFL number, • At this point, we are ready to run the simulation.
and the smoothing and damping of the solution across the cells, can be controlled in • Remember to adjust the numerics according to your physics.
the dictionary fvSolution, in the sub-dictionary PIMPLE.
• You can choose between running using global time stepping (directory uns) or local
time stepping (directory LTS).
PIMPLE • You will find the instructions of how to run the cases in the file README.FIRST
{ located in the case directory.
momentumPredictor yes;

nOuterCorrectors 1;
nCorrector 3;
nNonOrthogonalCorrectors 2;

maxCo 10; Maximum flow Courant


Maximum interface maxAlphaCo 1;
Courant
rDeltaTSmoothingCoeff 0.05; Local time step
Local time step rDeltaTDampingCoeff 0.5; smoothing
damping
Limit the maximum
maxDeltaT 1;
time-step size
}

915 916

Roadmap A crash introduction to compressible flows modeling OpenFOAM®

What are compressible flows?


A crash introduction to: • In few words, compressible flows are flows where the density change.

1. Turbulence modeling in OpenFOAM® • The changes in density can be due to velocity, pressure, or temperature
variations.
2. Multiphase flows modeling in • Compressible flows can happen at low speed (subsonic) or high speed
OpenFOAM® (transonic, supersonic, hypersonic and so on).
3. Compressible flows in OpenFOAM® • Buoyancy-driven flows are also considered compressible flows. After all, the
buoyancy is due to temperature gradients.
4. Moving bodies in OpenFOAM®
• In compressible flows, the viscosity also change with temperature.
5. Source terms in OpenFOAM® • Also, the thermodynamical variables are related via an equation of state
6. Scalar transport pluggable solver (e.g., ideal gas law).
• In principle, all flows are compressible.
• Usually, compressibility effects start to become significant when the Mach
number is higher than 0.3.
917 918
A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

A few compressible flows applications


• The following applications fall within the compressible flows classification:
• External and internal aerodynamics (high speed).
• Heat transfer and conjugate heat transfer
• Fire dynamics.
• Buoyancy driven flows Rayleigh–Bénard convection cells
Large Natural Convection Plume, as effect of combustion of excess
https://en.wikipedia.org/wiki/File:B%C3%A9nard_cells_convection.ogv
• Heating, ventilation, and air conditioning (HVAC). non-useable gases behind oilfield.
https://en.wikipedia.org/wiki/Plume_(fluid_dynamics)#/media/File:Naturalc
onvectionplume.JPG
• Thermal comfort.
• Turbomachinery.
• Combustion.
• Chemical reactions.
• Condensation, evaporation, and melting.
• And many more.
Iron melting Airplane thermal image
• As you can see, the range of applicability is very wide. https://commons.wikimedia.org/wiki/File:Iron_-melting.JPG http://www.blackroc.com/wp-content/uploads/2016/03/thermal-image.jpg
919 Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose 920

A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Compressible flows – Starting equations

NSE

Shadowgraph Images of Re-entry Vehicles Additional closure equations for:


Photo credit: NASA on the Commons.
https://www.flickr.com/photos/nasacommons/
turbulence models, multiphase models, combustion, particles, source
terms, equation of state, and so on
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose 921 922
A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Compressible flows – Boundary layer Compressible flows – Boundary layer

Thermal boundary layer vs. Viscous boundary layer Thermal boundary layer in function of Prandtl number (Pr)
Forced convection

Momentum and thermal boundary layer


• Just as there is a viscous boundary layer in the velocity distribution (or momentum), there is also a thermal
boundary layer. Horizontal heated plate immersed in a quiescent fluid. Vertical heated plate immersed in a quiescent fluid.
Natural convection Natural convection.
• Thermal boundary layer thickness is different from the thickness of the viscous sublayer (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
Natural convection in a heated plate
momentum sublayer thickness.
• As the fluid is warmed by the plate, its density decreases and a buoyant force arises which induces flow
• For fluids of low Prandtl numbers (e.g., air), it is much larger than the momentum sublayer thickness. motion in the vertical or horizontal direction.
• For Prandtl number equal 1, the thermal boundary layer is equal to the momentum boundary layer. 923 • The force is proportional to , therefore gravity must be considered. 924

A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Compressible solvers in OpenFOAM® Compressible solvers in OpenFOAM®


• Dealing with compressible flows in OpenFOAM® is not so different from what we have done so far. • OpenFOAM® comes with many solvers and models that can address a wide physics.
• The new steps are:
• Compressibility can be introduced in all the modeling capabilities we have seen so far
• Define the thermophysical variables.
(turbulence modeling and multiphase flows).
• Define the boundary conditions and initial conditions for temperature.
• If you are dealing with turbulence, you will need to define the boundary conditions and initial conditions • It is also possible to add source terms, deal with moving bodies or use adaptive mesh
for the turbulent thermal diffusivity (remember to choose the near-wall treatment). refinement.
• Define discretization schemes and linear solvers for the new variables and equations. • You will find the source code of all the compressible solvers in the directories:
• Additionally, the numerics of compressible solvers is a little bit more delicate.
• OpenFOAM-6/applications/solvers/compressible
• Temperature is a bounded quantity, so we need to use accurate and stable methods (preferably TVD).
• If you are in the presence of shock waves, you need to use TVD methods and gradient limiters. • OpenFOAM-6/applications/solvers/combustion
• The solvers are very sensitive to overshoots and undershoots in the gradients, so you need to use very • OpenFOAM-6/applications/solvers/heatTransfer
aggressive limiters.
• If you are dealing with chemicals reactions or combustion, you need to use accurate and stable methods
• OpenFOAM-6/applications/solvers/lagrangian
(preferably TVD). • OpenFOAM-6/applications/solvers/multiphases
• TVD methods requires good meshes and CFL number below 1 for good accuracy and stability.
• You will find the source code of the thermophysical models in the directory:
• Using steady solvers requires tuning of the under-relaxation factors. Usually, the default values do not
work well. • OpenFOAM-6/src/thermophysicalModels
• The use local time stepping to reach steady state can improve the convergence rate.
• FYI, we have found that it is tricky to achieve convergence using a low-RE approach with compressible flows
(high speed) and steady solvers. 925 926
A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Compressible solvers in OpenFOAM® Selecting thermophysical properties


• The thermophysical properties are set in the dictionary
• These are the compressible solvers that you will use most of the time in 1 thermoType thermophysicalProperties.
2 {
OpenFOAM®. 3 type hePsiThermo; • This dictionary file is located in the directory constant.
4 mixture pureMixture;
5 transport const; • Thermophysical models are concerned with energy, heat
• HVAC and low speed aerodynamics: 6
7
thermo
equationOfState
hConst;
perfectGas;
and physical properties.
• rhoSimpleFoam, rhoPimpleFoam 8
9
specie
energy
specie;
sensibleEnthalpy;
• In the sub-dictionary thermoType (lines 1-10), we define
10 } the thermophysical models.
11
• The entries in lines 3-4, are determined by the choice of
• High speed aerodynamics: 12
13
mixture
{ the solver (they are hardwired to the solver).
• sonicFoam, rhoSimpleFoam, rhoPimpleFoam 14
15
specie
{ • The transport keyword (line 5). concerns evaluating
16 nMoles 1; dynamic viscosity. In this case the viscosity is constant.
17 molWeight 28.9;
• Buoyancy driven flows (including Boussinesq approximation): 18 } • The thermodynamic models (thermo keyword) are
19 thermodynamics
concerned with evaluating the specific heat Cp (line 6). In
• buoyantBoussinesqPimpleFoam buoyantBoussinesqSimpleFoam, 20
21
{
Cp 1005; this case Cp is constant.
buoyantSimpleFoam, buoyantPimpleFoam 22 Hf 0;
• The equationOfState keyword (line 7) concerns to the
23 }
24 transport equation of state of the working fluid. In this case,
25 {
• Conjugate heat transfer 26 mu 1.84e-05;
27 Pr 0.713;
• chtMultiRegionFoam 28 }
29 }

927
• Line 8 is a fixed option (hardwired to the solver). 928

A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Selecting thermophysical properties Selecting thermophysical properties


• The form of the energy equation to be used is specified • When we use the sensible formulation
1 thermoType in line 9 (energy). 1 thermoType
2 { 2 {
(sensibleEnthalpy or sensibleInternalEnergy), the
3 type hePsiThermo; • In this case we are using enthalpy formulation 3 type hePsiThermo; heat of formation is not included in the energy equation.
4 mixture pureMixture; 4 mixture pureMixture;
5 transport const;
(sensibleEnthalpy). 5 transport const; • In the sub-dictionary mixture (lines 12-29), we define the
6 thermo hConst;
• In this formulation, the following equation is solved, 6 thermo hConst; thermophysical properties of the working fluid.
7 equationOfState perfectGas; 7 equationOfState perfectGas;
8 specie specie; 8 specie specie; • In line 17, we define the molecular weight.
9 energy sensibleEnthalpy; 9 energy sensibleEnthalpy;
10 } 10 } • In line 21, we define the specific heat.
11 11
12 mixture 12 mixture • The heat of formation is defined is line 22 (not used in
13 { • Alternatively, we can use the sensibleInternalEnergy 13 { the sensible formulation).
14 specie formulation, where the following equation is solved for 14 specie
15 { the internal energy, 15 { • In this case, we are defining the properties for air at 20°
16 nMoles 1; 16 nMoles 1; Celsius and at a sea level.
17 molWeight 28.9; 17 molWeight 28.9;
18 } 18 } • As we are using the transport model const (line 5), we
19 thermodynamics 19 thermodynamics
20 { 20 {
need to define the dynamic viscosity and Prandtl number
21 Cp 1005; • In the previous equations, the effective thermal diffusivity 21 Cp 1005; (lines 26 and 27).
22 Hf 0; 22 Hf 0;
23 }
is equal to, 23 } • If you set the viscosity to zero, you solve the Euler
24 transport 24 transport equations.
25 { 25 {
26 mu 1.84e-05; 26 mu 1.84e-05; • Remember, transport modeling (line 5), concerns
27 Pr 0.713; 27 Pr 0.713;
evaluating dynamic viscosity, thermal conductivity and
28 } 28 }
thermal diffusivity.
29 } • And is the kinetic energy per unit mass. 29 }

929 930
A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Selecting thermophysical properties Adjusting the numerical method


• If you choose the sensibleEnthalpy formulation, you need to define the convective
• When we use the sensible formulation
1 thermoType discretization schemes and linear solvers of the energy equation (enthalpy formulation).
2 {
(sensibleEnthalpy or sensibleInternalEnergy), the
3 type hePsiThermo; heat of formation is not included in the energy equation. fvSchemes fvSolution
4 mixture pureMixture;
5 transport sutherland; • If you want to include the heat of formation, you must use
6 thermo hConst; the absoluteEnthalpy formulation (line 6). divSchemes “( | | )”
7 equationOfState perfectGas; { {
8 specie specie; • If you use the transport model sutherland (line 5), you div(phi,T) Gauss linearUpwind Grad(T); solver PBiCGStab;
9 energy sensibleEnthalpy; will need to define the coefficients of the Sutherland
10 } div(phi,K) Gauss linear; preconditioner DILU;
11 model. div(phi,h) Gauss linear; tolerance 1e-8;
12 mixture
• The Sutherland model is defined as follows … relTol 0.01;
13 {
14 specie (OpenFOAM® uses the 2 coefficients formulation): … }
15 { … …
16 nMoles 1; } …
17 molWeight 28.9;
18 }

19 thermodynamics
20 {
21 Cp 1005;
22 Hf 0;
• The Sutherland coefficients are defined in lines 26-27.
23 }
• Remember, temperature is a bounded quantity so you need to use non-oscillatory methods.
24 transport
25 { • For low speed flows, the kinetic energy K and the enthalpy h can be discretized using the linear
26 As 1.4792e-06; • Remember, you can use the banana method method. For high speed flows, is better to use bounded methods.
27 Ts 116; to know all the options available.
28 } • Remember to use gradient limiters.
29 }

931 • If you are using a steady solver, remember to set the under relaxation factors for h, T, and rho.932

A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®

Adjusting the numerical method Transport properties – Boussinesq solvers


• If you choose the sensibleInternalEnergy formulation, you need to define the convective
• If you use the family of solvers that uses the Boussinesq
discretization schemes and linear solvers of the energy equation (internal energy formulation). transportModel Newtonian; approximation, you do not need to define the
fvSchemes fvSolution // Laminar viscosity thermodynamical properties.
nu nu [0 2 -1 0 0 0 0] 1e-05;
• Instead, you need to define the transport properties (as
divSchemes “( | | )” // Thermal expansion coefficient for incompressible flows) and a reference temperature.
{ { beta beta [0 0 0 -1 0 0 0] 3e-03;
• You will need to define the following fluid properties:
div(phi,T) Gauss linearUpwind Grad(T); solver PBiCGStab; // Laminar Prandtl number laminar viscosity, thermal expansion coefficient, laminar
div(phi,K) Gauss linear; preconditioner DILU; Pr Pr [0 0 0 0 0 0 0] 0.9;
Prandtl number, and turbulent Prandtl number.
div(phi,e) Gauss linear; tolerance 1e-8;
div(phiv,p) Gauss linear; relTol 0.01; // Turbulent Prandtl number • The following solvers use the Boussinesq approximation:
Prt Prt [0 0 0 0 0 0 0] 0.7;
… }
• buoyantBoussinesqPimpleFoam
… … // Reference temperature
… … TRef TRef [0 0 0 1 0 0 0] 300; • buoyantBoussinesqSimpleFoam.
} … • Remember, the Boussinesq approximation is a way to
solve natural convection problems, without having to
solve the compressible NSE.
• Remember, temperature is a bounded quantity so you need to use non-oscillatory methods. • It assumes that variations in density have no effect on
the flow field, except when they give rise to buoyancy
• For low speed flows, the kinetic energy K and the internal energy e can be discretized using the
forces.
linear method. For high speed flows, is better to use bounded methods.
• This approximation is accurate when density variations
• Remember to use gradient limiters. are small.
• If you are using a steady solver, remember to set the under relaxation factors for e, T, and rho.933 934
A crash introduction to compressible flows modeling OpenFOAM® Compressible flows hands-on tutorials
Final remarks
• When solving the enthalpy formulation of the energy equation, • 2D Heated cylinder – Thermal plumes
• Let us run this case. Go to the directory:

the pressure work term can be excluded from the solution. $PTOFC/advanced_physics/compressible/2Dcylinder_plumes/buoyantPimpleFoam/

• 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.

• 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.
• Finally, when you work with compressible solvers you use absolute • 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
pressure and the working units are in Pascals.
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.
935 936

Compressible flows hands-on tutorials Compressible flows hands-on tutorials


2D Heated cylinder – Thermal plumes 2D Heated cylinder – Thermal plumes

• The cylinder and the bottom surface are heated. • In this case we will use the solver buoyantPimpleFoam.
• This family of solvers is specifically formulated for buoyancy driven flows and HVAC
applications.
• When we deal with buoyant flows, we also need to define the gravity vector. This is done in the
dictionary constant/g.
• As the flow is compressible, we need to define the thermodynamical properties of the working
fluid.
• This is done in he dictionary constant/thermophysicalProperties.
• We also need to define the boundary conditions and initial conditions for the temperature field.
• Finally, adjust the numerics according to your physics.
• As an exercise, try to use the different formulations of the energy equation and compare the
solutions.
• Alternatively, you can use the solver buoyantBoussinesqPimpleFoam, which instead of
Temperature contours Temperature contours solving the energy equation it uses the Boussinesq approximation.
No turbulent model K-omega SST turbulent model • You will find the instructions of how to run the cases in the file README.FIRST located in the
http://www.wolfdynamics.com/training/compressible/image1.gif http://www.wolfdynamics.com/training/compressible/image2.gif
case directory.

937 938
Compressible flows hands-on tutorials Compressible flows hands-on tutorials
2D supersonic cylinder – Shock waves
• 2D supersonic cylinder – Shock waves
• Let us run this case. Go to the directory:

$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.
Shock wave visualization using numerical Schlieren (density gradient)
• 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 • Shock waves are strong discontinuities that need to be treated using high resolution
you will get used with the command line interface and OpenFOAM® commands. schemes.
• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases. • Additionally, the non-orthogonality add extra complications to this problem.
939 940

Compressible flows hands-on tutorials Compressible flows hands-on tutorials


2D supersonic cylinder – Shock waves 2D supersonic cylinder – Shock waves
• In this case we will use the solver sonicFoam.
• This solver is specifically formulated for trans-sonic/supersonic flows.
• The solver is unsteady, 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.
• Finally, adjust the numerics according to your physics.
• Alternatively, you can use the solver rhoPimpleFoam, but you will need to enable
transonic corrections.
Mach number contours Schlieren contours • This is done in the PIMPLE block of the dictionary fvSolution ( transonic yes; ).
http://www.wolfdynamics.com/training/compressible/image3.gif http://www.wolfdynamics.com/training/compressible/image4.gif

• You will find the instructions of how to run the cases in the file README.FIRST
located in the case directory.
941 942
Roadmap A crash introduction to moving bodies OpenFOAM®

Moving bodies in OpenFOAM® – A few examples


A crash introduction to:
1. Turbulence modeling in OpenFOAM®
2. Multiphase flows modeling in
OpenFOAM®
3. Compressible flows in OpenFOAM® Sloshing tank Oscillating cylinder (prescribed motion)
http://www.wolfdynamics.com/training/dynamicMeshes/sloshing1.gif http://www.wolfdynamics.com/training/dynamicMeshes/meshMotion1

4. Moving bodies in OpenFOAM®


5. Source terms in OpenFOAM®
6. Scalar transport pluggable solver

Prescribed motion with multiple bodies Layering with mesh zones interface
943 http://www.wolfdynamics.com/training/dynamicMeshes/meshMotion1 http://www.wolfdynamics.com/training/dynamicMeshes/layeringMesh.gif944

A crash introduction to moving bodies OpenFOAM® A crash introduction to moving bodies OpenFOAM®

Moving bodies in OpenFOAM® – A few examples Moving bodies in OpenFOAM®


• OpenFOAM® comes with many solvers and models that can address a wide physics.
• Moving bodies can be added to all the modeling capabilities we have seen so far
(turbulence modeling, multiphase flows, and compressible flows).
• Several class of motions can be simulated in OpenFOAM®:
• Prescribed motion.
• Rigid body motion.
Sea keeping Continuous stirring tank reactor (CSTR)
http://www.wolfdynamics.com/training/dynamicMeshes/seakeeping.gif http://www.wolfdynamics.com/training/movingbodies/image13.gif
• Sliding meshes.
• MRF.

• 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.

Falling body (6 DoF) VOF with sliding meshes


http://www.wolfdynamics.com/training/movingbodies/image5.gif http://www.wolfdynamics.com/training/mphase/image33.gif 945 946
A crash introduction to moving bodies OpenFOAM® A crash introduction to moving bodies OpenFOAM®

Moving bodies in OpenFOAM® Moving bodies in OpenFOAM®


• The mesh motion solver is selected in the dictionary constant/dynamicMeshDict. • You will find the source code of all the mesh motion libraries in the directories:
• In the case of prescribed motion of a boundary patch, the motion is assigned in the • OpenFOAM-6/src/dynamicFvMesh
dictionary 0/pointDisplacement. • OpenFOAM-6/src/dynamicMesh
• Also, the boundary type of the moving walls must be movingWallVelocity, this is set • OpenFOAM-6/src/fvMotionSolver
in the dictionary 0/U.
• OpenFOAM-6/src/rigidBodyDynamics
• And as usual, you will need to adjust the numerics according to your physics.
• OpenFOAM-6/src/rigidBodyMeshMotion
• To use the moving bodies capabilities, you will need to use solvers able to deal with
dynamic meshes. • OpenFOAM-6/src/sixDoFRigidBodyMotion

• The solvers able to deal with dynamic meshes contain the word DyM in their name.
• To find which solvers work with dynamic meshes, go to the solvers directory by typing • You will find the source code of the prescribed patch motion in the directory:
sol in the command line interface. Then type in the terminal: • OpenFOAM-6/src/fvMotionSolver/pointPatchFields/derived
• $> find . -iname “*DyM*”
• A few solvers that work with dynamic meshes: interDyMFoam, pimpleDyMFoam, • You will find the source code of the restraints/constraints of rigid body motion solvers
rhoPimpleDyMFoam, sonicDyMFoam. in the directory:
• OpenFOAM-6/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion
947 948

Moving bodies hands-on tutorials Moving bodies hands-on tutorials


Continuous stirring tank reactor – Sliding meshes and MRF
• Continuous stirring tank reactor – Sliding meshes and
MRF
• Let us run this case. Go to the directory:

$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, Sliding grids – Unsteady solver MRF – Steady solver
run_mesh.sh, run_sampling.sh, run_solver.sh, and so on. These files can be used to run the case http://www.wolfdynamics.com/training/movingbodies/image13.gif http://www.wolfdynamics.com/training/movingbodies/image14.gif

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.
949 950
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF Continuous stirring tank reactor – Sliding meshes and MRF
• We already created this mesh during the meshing module. • In the MRF approach, the governing equations are solved in a relative rotating frame
• We will only address the differences in meshing for a MRF simulation and a sliding mesh in the selected rotating zone.
simulation. • Additional source terms that model the rotation effect are taken into account.
• In this case, at the end of the meshing stage we obtained a faceZone and a cellZone.
• You select the rotating zone and set the rotation properties in the dictionary
• This is a conforming mesh, that is, the cells in the interface of the inner and outer regions are constant/MRFProperties.
perfectly matching.
• In this case, the mesh is conforming.
• 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
Shaft
mesh in two regions and create the interface patches between the fix zone and the rotating type rotatingWallVelocity;
zone (the solution will be interpolated in these patches). origin (0 0 0);
axis (0 0 1);
omega constant 12.566370;
value uniform (0 0 0);
Cell region 2
(fix region)s
Impeller
type movingWallVelocity;
value uniform (0 0 0); Inner region generated during
meshing - MRFProperties
Face region between fix and
rotating regions Cell region 1
(face_inner_volume) (cell_inner_volume)

951 952

Moving bodies hands-on tutorials Moving bodies hands-on tutorials


Continuous stirring tank reactor – Sliding meshes and MRF Continuous stirring tank reactor – Sliding meshes and MRF
• In the sliding meshes approach, the selected rotating region is physically rotating. Shaft
type rotatingWallVelocity;
• As the meshes are non-conforming, the solution between the rotating region and the origin (0 0 0);
fix region must be interpolated using arbitrary mesh interface. axis (0 0 1);
omega constant 12.566370;
• In the sliding meshes approach, is not enough to only identify the rotating region. value uniform (0 0 0);

• We also need to create the interface patches between the fix zone and the rotating Impeller
zone. type movingWallVelocity;
value uniform (0 0 0); Inner region and arbitrary mesh
interface

Shaft
type rotatingWallVelocity;
origin (0 0 0);
axis (0 0 1); constant/dynamicMeshDict – For sliding meshes constant/MRFProperties – For MRF approach
omega constant 12.566370;
value uniform (0 0 0);
cellZone cell_inner_volume;
dynamicFvMesh dynamicMotionSolverFvMesh; active yes;
Impeller motionSolverLibs ( "libfvMotionSolvers.so" );
type movingWallVelocity; solver solidBody; // Fixed patches (by default they move’ with the MRF zone)
value uniform (0 0 0); Inner region – dynamicMeshDict cellZone cell_inner_volume; nonRotatingPatches ();
solidBodyMotionFunction rotatingMotion;
Arbitrary mesh interface – origin (0 0 0); origin (0 0 0);
createBafflesDicts axis (0 0 1); axis (0 0 1);
omega constant 12.566370; omega constant 12.566370;
953 954
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF Continuous stirring tank reactor – Sliding meshes and MRF
• For siding meshes, we need to create separated regions. • The utility createBaffles, reads the dictionary createBafflesDict.
• In this case, to create the two regions we proceed as follows, • With this utility we create the interface patches between the fix zone and the
rotating zone.

1. $> createBaffles –overwrite


2. $> mergeOrSplitBaffles –split –overwrite 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
{
• In step 1, we split the mesh in regions using the baffles (faceZone), created during the meshing master Parameters for the master patch
{
stage. Boundary condition
name AMI1; Name of the master patch (user defined)
type cyclicAMI;
for sliding grids matchTolerance 0.0001;
• We also create the cyclicAMI patches AMI1 and AMI2. neighbourPatch AMI2; Neighbour patch (slave patch or AMI2)
transform noOrdering;

• At this point we have two regions and one zone. However, the two regions are stich together }
slave Parameters for the slave patch
{
via the patches AMI1 and AMI2. Boundary condition name AMI2; Name of the slave patch (user defined)
type cyclicAMI;
for sliding grids
• In step 2, we topologically split the patches AMI1 and AMI2. As we removed the link between matchTolerance 0.0001;
neighbourPatch AMI1; Neighbour patch (master patch or AMI1)
transform noOrdering;
AMI1 and AMI2, the regions are free to move. }
}
}
} Initially, the master and slave patches
955 share a common face 956

Moving bodies hands-on tutorials Moving bodies hands-on tutorials


Continuous stirring tank reactor – Sliding meshes and MRF Continuous stirring tank reactor – Sliding meshes and MRF

• In sliding mesh simulations, the solution is interpolated back-and-forth • At this point the mesh is ready to use. You can visualize the mesh using
between the regions. paraFoam.
• The interpolation is done at the arbitrary mesh interface patches (AMI) . • If you use checkMesh, it will report that there are two regions.
• To reduce interpolation errors at the AMI patches, the meshes should be • In the dictionary constant/dynamicsMeshDict we set which region will
similar in the master and slave patches. move and the rotation parameters.
AMI interface Fix domain • To preview the region motion, in the terminal type:
http://www.wolfdynamics.com/training/movingbodies/image8.gif • $> 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 an step-by-step video explaining


Rotating domain Rotating patch Fix patch this case.
Master patch Slave patch 957 958
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF Continuous stirring tank reactor – Sliding meshes and MRF

• The command moveDynamicMesh –checkAMI • At this point, we are ready to run the simulation.
will print on screen the quality of the AMI interfaces
for every time step. • You can choose between running using sliding meshes (directory
• Ideally, you should get the AMI patches weights as sliding_psio) or MRF (directories MRF_piso or MRF_simple).
close as possible to one.
• If you run the sliding meshes case, you will use the solver pimpleDyMFoam.
• Weight values close to one will guarantee a good
interpolation between the AMI patches. • If you run the MRF approach case, you can use the solver simpleFoam
http://www.wolfdynamics.com/training/movingbodies/image9.gif (steady solution) or pimpleFoam (unsteady solution).
… Name of the AMI patch Name of the AMI patch • You will find the instructions of how to run the cases in the file


README.FIRST located in the case directory.
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




959 960

Moving bodies hands-on tutorials Moving bodies hands-on tutorials


Oscillating cylinder – Prescribed motion
• Oscillating cylinder – Prescribed motion Moving boundary

• Let us run this case. Go to the directory: http://www.wolfdynamics.com/training/movingbodies/image10.gif

$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 Cylinder prescribed motion – Oscillating motion
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.
961 962
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Oscillating cylinder – Prescribed motion Oscillating cylinder – Prescribed motion
• In the dictionary constant/dynamicMeshDict we select the mesh morphing • In the dictionary 0/pointDisplacement we select the prescribed body motion.
method and the boundary patch that it is moving (lines 21 and 25, respectively). • In this case we are using oscillatingDisplacement (line 44) for the cylinder patch.
• There are many mesh morphing methods implemented in OpenFOAM®. • Each method has different input values. In this case it is required to define the
• Mesh morphing is based in diffusing or propagating the mesh deformation all over the amplitude (line 45) and the angular velocity (line 46) in rad/s.
domain. • If the patch is not moving, we assign to it a fixedValue boundary conditions (lines 37-
• You will need to find the best method for your case. 41).
• But in general, the setup used in this case works fine most of the times.
37 in
17 dynamicFvMesh dynamicMotionSolverFvMesh; Mesh motion library for 38 {
boundary patches
18 39 type fixedValue;
19 motionSolverLibs ("libfvMotionSolvers.so"); Motion library 40 value uniform (0 0 0);
20 41 }
Method coefficients

21 solver displacementLaplacian; Solver for mesh motion 42 cylinder


22 method 43 {
23 displacementLaplacianCoeffs 44 type oscillatingDisplacement;
24 { 45 amplitude ( 0 1 0 );
25 diffusivity inverseDistance (cylinder); 46 omega 6.28318;
26 } 47 value uniform ( 0 0 0 ); Dummy value for paraview
48 }
Mesh diffusion method Patch name 963 964

Moving bodies hands-on tutorials Moving bodies hands-on tutorials


Oscillating cylinder – Prescribed motion Oscillating cylinder – Prescribed motion
• If you are dealing with turbulence modeling and you want to use wall functions, you
• At this point, we are ready to run the simulation.
will need to assign the movingWallVelocity boundary condition to the moving patch.
• This is done in the dictionary 0/U. • 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.
41 cylinder
42 { • During this check, you can use large time-steps as we re not computing the
43 type movingWallVelocity;
44 value uniform (0 0 0);
solution, we are only interested in checking the motion.
45 } • To check the mesh motion, type in the terminal:

• And as usual, you will need to adjust the numerics according to your physics.
1. $> moveDynamicMesh -noFunctionObjects
• 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).
965 966
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Floating body – Rigid body motion
• Floating body – Rigid body motion
ente of av ity position

• Let us run this case. Go to the directory:

position
c
$PTOFC/advanced_physics/rigid_body_motion/floatingBody

ime/ s

http://www.wolfdynamics.com/training/movingbodies/image11.gif
t v s o ientation u (acos( ) /pi/ )

• 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.

position
• You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,

c
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. ime/ s

• If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases. http://www.wolfdynamics.com/training/movingbodies/image12.gif

967 Floating body simulation with VOF and turbulence modeling. 968

Moving bodies hands-on tutorials Moving bodies hands-on tutorials


Floating body – Rigid body motion Floating body – Rigid body motion
• As for prescribed motion, in rigid body motion the mesh morphing is based in diffusing • The dictionary constant/dynamicMeshDict (continuation).
or propagating the mesh deformation all over the domain.
• In the dictionary constant/dynamicMeshDict we select the mesh morphing 23 sixDoFRigidBodyMotionCoeffs
library and rigid body motion library (lines 17-21). 24 {
25 patches (floatingObject); Moving patch
• The rigid motion solver will compute the response of the body to external forces. 26
Mesh deformation limits.
27 innerDistance 0.1;
The mesh will not be deformed in the fringe located within
• In lines 23-78, we define all the inputs required by the rigid motion solver. 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);
17 dynamicFvMesh dynamicMotionSolverFvMesh; Mesh motion library for
boundary patches
18 37 report on; Report on screen position of the body
19 motionSolverLibs ("libsixDoFRigidBodyMotion.so"); 38
Motion library outerDistance
20 45 solver
Method coefficients

21 solver sixDoFRigidBodyMotion; Solver for mesh motion 46 {


22 method 47 type Newmark; Rigid body motion solver
23 sixDoFRigidBodyMotionCoeffs 48 }
24 { …
Body patch
… …
… …

78 } innerDistance
969 Set it to zero if you do not want to apply mesh morphing to the inner region 970
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Floating body – Rigid body motion Floating body – Rigid body motion
• The dictionary constant/dynamicMeshDict (continuation). • 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
50 constraints
the boundary condition calculated.
51 {
55 fixedAxis
56 { 33 floatingObject
57 sixDoFRigidBodyMotionConstraint axis; 34 {
58 axis (0 1 0); 35 type calculated;
59 } Motion constraints 36 value uniform (0 0 0);
If you do not give any 37 }
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);
• If you are dealing with turbulence modeling and you want to use wall functions, you
68 } will need to assign the movingWallVelocity boundary condition to the moving patch.
70 } • This is done in the dictionary 0/U.
Body restraints
72 restraints
Restraints can be used to
73 { 33 floatingObject
damp the acceleration of the
76 }
body. 34 {
In this case, we are not 35 type movingWallVelocity;
using restraints
78 } 36 value uniform (0 0 0);
37 }
971 972

Moving bodies hands-on tutorials Roadmap


Floating body – Rigid body motion
• And as usual, you will need to adjust the numerics according to your physics.
A crash introduction to:
• In the case directory, you will find the script extractData.
• This script can be used to extract the position of the body during the 1. Turbulence modeling in OpenFOAM®
simulation.
2. Multiphase flows modeling in
• In order to use the extractData script, you will need to save the log file of
the simulation.
OpenFOAM®
• At this point, we are ready to run the simulation. 3. Compressible flows in OpenFOAM®
• We will use the solver interDyMFoam. 4. Moving bodies in OpenFOAM®
• You will find the instructions of how to run the cases in the file
README.FIRST located in the case directory. 5. Source terms in OpenFOAM®
6. Scalar transport pluggable solver

973 974
A crash introduction to source terms OpenFOAM® A crash introduction to source terms OpenFOAM®

Source terms in OpenFOAM® Source terms in OpenFOAM®


• In addition to all modeling capabilities we have seen so far, you can also add source • To use source terms, you must first select where you want to apply it
terms to the governing equations without the need of modifying the original source • You can apply a source term in the whole domain, a set of cells, a cell zone, or a
code. point (or group of points).
• This functionality is provided via the dictionary fvOptions, which is located in the • You can create the set of cells at meshing time or you can use the utility topoSet to
directory system.
select a group of cells.
• There are many source terms implemented in OpenFOAM®, you can even use • By the way, boundary conditions are source terms added at the boundary patches,
codeStream to program your own source term without the need of recurring to high and MRF are source terms added to a cell selection.
level programming.
• The fvOptions functionality work with most of the solvers that deal with advanced Set of cell
modeling capabilities.
• Remember, the solver icoFoam is very basic with no modeling capabilities.
Therefore you can not use the fvOptions functionality and many other modeling
and postprocessing capabilities with it.
• You will find the source code of the source terms in the directory:
• OpenFOAM-6/src/fvOptions Point selection

975 976

A crash introduction to source terms OpenFOAM® Source terms hands-on tutorials


Source terms in OpenFOAM®
• The source terms can be selected in the dictionary
• Filter source term
• Let us run this case. Go to the directory:
1 user_defined_name fvOptions, and they can be modified on-the-fly.
2 {
3 type name_of_source_term; • This dictionary file is located in the directory system.
4
5 active true; • Hereafter we show a generic fvOptions dictionary.
6
7 input_coefficients • According to the source term you selected, you will need
8 {
to give different input parameters in the input coefficients $PTOFC/advanced_physics/source_terms/filter/porous_source
9 timeStart 0.5;
10 duration 2.0; section (lines 7-23).
11
12 selectionMode points; • The input parameters indicated with an arrow can be
13 points used with any source term. Most of then are self
14 ( explanatory.
15 (3 0 0)
16 ); • The volumeMode keyword (line 21) let you choose
17
18 //selectionMode cellZone;
between absolute and specific. • In the case directory, you will find the README.FIRST file. In this file, you will find the general instructions of
19 //cellZone filter; how to run the case. In this file, you might also find some additional comments.
20
• absolute: input values are given as quantity
21 volumeMode absolute; • You will also find a few additional files (or scripts) with the extension .sh, namely, run_all.sh,
• specific: input values are given as quantity/m3
22 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.
...
... • Remember, you can use the banana method to know all • We highly recommend to open the README.FIRST file and type the commands in the terminal, in this way
23 }
source terms and options available. you will get used with the command line interface and OpenFOAM® commands.
24 }
• You can also read the source code. • If you are already comfortable with OpenFOAM®, use the automatic scripts to run the cases.
977 978
Source terms hands-on tutorials Source terms hands-on tutorials
Filter source term Filter source term
• In this case we are going to use the source term explicitPorositySource. system/fvOptions
• The source terms can be selected in the
• Using this source term we can apply a porous region (e.g., Darcy-Forchheimer) in the 17 filter1
dictionary fvOptions, and they can be modified
18 {
cell selection. 19 type explicitPorositySource; on-the-fly.
20 active yes;
• The source term is activated after 2 seconds of simulation time. 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).
Set of cell
38 DarcyForchheimerCoeffs
(filter)
39 { • The source term is used in a cellZone (line 28)
41 d (5000000 5000000 5000000); named filter (line 29), this zone must be created
44 f (0 0 0);
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 }
http://www.wolfdynamics.com/training/sourceterms/image1.gif 979 980

Source terms hands-on tutorials Source terms hands-on tutorials


Filter source term Filter source term
system/topoSetDict system/topoSetDict
• To create the cellZone used in fvOptions, we • To create the cellZone used in fvOptions, we
first create a cellSet. first create a cellSet.
• The set of cells (cellSet) is constructed using the • Now that we have the cellSet filter, we can
utility topoSet. convert it to a cellZoneSet that can be used by
fvOptions.
• This utility reads the dictionary topoSetDict,
which is located in the directory system. • The name of the new cellZoneSet is filter.
actions • Hereafter we show the dictionary inputs used to actions • Remember, you can apply the source terms in a
( create the cellSet named filter. ( cellSet or in a cellZone.
// filter ...
{ ...
name filter; Name of the selection ...
{
type cellSet; Select a set of cells name filter; Name of the selection
action new; Create a new selection type cellZoneSet; Select a zone set (cellZoneSet)
source boxToCell; action new; Create a new selection
sourceInfo
{ Use a box to select the set of cells source setToCellZone;
box (1.5 -10 -10) (2 10 10); sourceInfo
} {
Convert the cellSet filter to a cellZoneSet
} set filter; named filter
... }
... }
... )
)
981 982
Source terms hands-on tutorials Roadmap
Filter source term

• At this point, we are ready to run the simulation. A crash introduction to:
• We will use the solver pimpleFoam, which can use source terms.
• Before running the simulation, remember to use the utility topoSet to create
1. Turbulence modeling in OpenFOAM®
the filter region used by the source term. 2. Multiphase flows modeling in
• You can visualize the region using paraview. OpenFOAM®
• Finally, remember to adjust the numerics according to your physics.
3. Compressible flows in OpenFOAM®
• You will find the instructions of how to run the cases in the file
README.FIRST located in the case directory. 4. Moving bodies in OpenFOAM®
5. Source terms in OpenFOAM®
6. Scalar transport pluggable solver

983 984

Scalar transport pluggable solver Scalar transport pluggable solver

The functionObject scalarTransport The functionObject scalarTransport


• The scalar transport functionObject is defined in
• In addition to all modeling capabilities we have seen so far, you can also add the dictionary controlDict.
scalar transport equations (or convection-diffusion equation), without the • Remember, the input parameters can be modified
need of modifying the original source code. scalar1 on-the-fly.
{
• This functionality is provided via functionObjects, and it can be seen as a type scalarTransport;
functionObjectLibs ("libsolverFunctionObjects.so"); Select scalarTransport functionObject
solver that can be plug into another one. enabled true;

• To setup the scalar transport equation you need to: writeControl outputTime;
Number of corrector iterations.
• Define the functionObject in the dictionary controlDict. log yes; It is recommended to do t least one iteration.

nCorr 1;
• Add the discretization schemes and linear solvers for the new equations. Diffusion coefficient.
D 0; If turbulent modeling is in use, you can define the
//alphaD 0;
• Define the boundary conditions and initial conditions of the transported //alphaDt 0;
laminar diffusion coefficient alphaD and the turbulent
diffusion coefficient alphaDt
scalars.
Name of the new field. You will need to select the
• You will find the source code of the scalar transport pluggable solver in the discretization schemes and linear solvers for this field.
You will also need to define the boundary conditions
directory: field s1; and initial conditions for this field.

• OpenFOAM-6/src/functionObjects/solvers
//schemesField U; Option to use the same numerical scheme as the one
} used for the filed U
985 986
Scalar transport pluggable solver Scalar transport pluggable solver

Boundary conditions Discretization schemes and linear solvers


0/s1 • Finally, and assuming that you named the new scalar s1, you need to define the
discretization schemes and linear solvers of the new equations.
• 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 • Remember, this is a bounded quantity so it is a good idea to use TVD schemes and
initial conditions for the field s1. gradient limiters.
internalField uniform 0;
• This is done in the dictionary 0/s1.
boundaryField
{ • In this case, the scalar is entering in the patch system/fvSchemes system/fvSolution
walls
{ inlet with a value of 1 (this is a concentration
type zeroGradient; therefore it has no dimensions). gradSchemes s1
} { {
inlet
• The initial concentration of the scalar is zero. default Gauss linear; solver smoothSolver;
{ grad(s1) cellLimited Gauss linear 1; smoother symGaussSeidel;
type fixedValue;
} tolerance 1e-08;
value uniform 1;
relTol 0;
}
}
divSchemes
outlet
{ {
type inletOutlet; default none;
inletValue uniform 0;
value uniform 0;
div(phi,U) Gauss linearUpwindV default;
} div(phi,s1) Gauss vanLeer;
} }

987 988

Scalar transport pluggable solver hands-on tutorials Scalar transport pluggable solver hands-on tutorials
Scalar transport in an elbow – Internal geometry
• Scalar transport in an elbow – Internal geometry • Notice that we are adding two scalars, s1 and s2.

• Let us run this case. Go to the directory:

$PTOFC/advanced_physics/source_terms/2Delbow_passive_scalar S1
U → (2 0 0)

http://www.wolfdynamics.com/training/sourceterms/image2.gif
S2
U → (0 3 0)
• 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.
989 http://www.wolfdynamics.com/training/sourceterms/image3.gif 990
Scalar transport pluggable solver hands-on tutorials This is the end
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.
• Some kind of conclusion,
• Do not forget to create the boundary conditions and initial conditions of the
new field variables. • Good mesh – good results.
• You will find the instructions of how to run the cases in the file
README.FIRST located in the case directory. • Start robustly and end with accuracy.
• Stability, accuracy and boundedness, play
by these terms and you will succeed.
• Select wisely the boundary conditions.

991

This is the end This is the end


• We hope you have found this training useful and we hope to see you in one of our advanced
That was only the tip of the iceberg training sessions:
• OpenFOAM® – Multiphase flows
• OpenFOAM® – Naval applications
• OpenFOAM® – Turbulence Modeling
• OpenFOAM® – Computational heat transfer and compressible flows
• OpenFOAM® – Advanced meshing
• OpenFOAM® – Basic programming
• Introduction to the Finite Volume Method
• DAKOTA – Optimization methods and code coupling
• Python – Programming, data visualization and exploratory data analysis
• Python and R – Data science and big data
• ParaView – Advanced scientific visualization and python scripting
• And many more available on request
• Besides consulting services, we also offer ‘Mentoring Days’ which are days of one-on-one
coaching and mentoring on your specific problem.
Now the rest is on you • For more information, ask your trainer, or visit our website
http://www.wolfdynamics.com/
This is the end

TGIF & TGIO Supplements


You can download the supplement slides in the following link:
Enjoy OpenFOAM® http://www.wolfdynamics.com/tutorials.html?layout=edit&id=50

Training material
You can download the training material in the following link:
http://www.wolfdynamics.com/tutorials.html?layout=edit&id=50

You might also like