Openfoam 2x2 PDF
Openfoam 2x2 PDF
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:
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.
Roadmap
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
• 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
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
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.
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
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*”
27 28
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
39 40
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
sampling paraview
$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)
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
Zoom
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
Select Surface in the • You can access all the filters from the menu Filter.
Representation Toolbar
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
4. Press Apply
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
3. Press Apply
3. Press Apply
2. Filter options
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.
• 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
3. gnuplot> plot ‘logs/p_0’ using 1:2 with lines, ‘logs/pFinalRes_0’ using 1:2 with lines
Here we are plotting to different files. You can concatenate files using comma (,)
4. gnuplot> reset
To reset the scales
7. gnuplot> plot [30:50][] ‘logs/Ux_0’ u 1:2 w l title ‘Ux’,‘logs/Uy_0’ u 1:2 w l title ‘Uy’
Set the x range from 30 to 50 and plot tow files and set legend titles
8. gnuplot> exit
To exit gnuplot • 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
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)
• The transportProperties file is a dictionary for the dimensioned scalar nu, or the 2 Length meters m
kinematic viscosity.
3 Time second s
• The values between square bracket are the units. 7 Luminuous intensity candela cd
• 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
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
• 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
• 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,
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
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
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
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.
file: /home/joegi/my_cases_course/6/101OF/cavity/system/controlDict from line 17 to line 69. Valid patchField types are :
...
• Missing file points in directory polyMesh. Likely you are missing the mesh. ...
...
FOAM exiting
file: /home/joegi/my_cases_course/6/101OF/cavity/0/U.boundaryField.movingWall from line 25 to line 26.
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 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® 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/
• Remember, you have the source code there so you can always
check the original source.
139 140
141 142
3D Dam break – Free surface flow 3D Dam break – Free surface flow
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
145 146
3D Dam break – Free surface flow 3D Dam break – Free surface flow
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
}
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 }
153 154
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/p_rgh The file 0/U
155 156
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/k The file 0/epsilon
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
}
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
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
• 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:
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:
2. Select alpha.water in
the Active Variable drop-
down menu 1. Select the filter Contour
4. Press apply
Interface
alpha.water = 0.5
179 180
3D Dam break – Free surface flow 3D Dam break – Free surface flow
181 182
Roadmap Flow past a cylinder – From laminar to turbulent flow
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
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
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
[1] Russel and Wang (N) 1.38 ± 0.007 ± 0.322 1.29 ± 0.022 ± 0.50
[2] Calhoun and Wang (N) 1.35 ± 0.014 ± 0.30 1.17 ± 0.058 ± 0.67
[3] Braza et al. (N) 1.386± 0.015 ± 0.25 1.40 ± 0.05 ± 0.75
[4] Choi et al. (N) 1.34 ± 0.011 ± 0.315 1.36 ± 0.048 ± 0.64
[5] Liu et al. (N) 1.35 ± 0.012 ± 0.339 1.31 ± 0.049 ± 0.69
[1] D. Rusell and Z. Wang. A cartesian grid method for modeling multiple moving objects in 2D incompressible viscous flow. Journal of Computational Physics, 191:177-205, 2003.
[2] D. Calhoun and Z. Wang. A cartesian grid method for solving the two-dimensional streamfunction-vorticity equations in irregular regions. Journal of Computational Physics. 176:231-275, 2002. 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.
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 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.
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
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
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
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
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.
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
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
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
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.
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
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
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
• 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
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
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
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
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
Feature toolbar:
Selection
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.
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
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
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
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
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.
287 288
• 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
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
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.
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
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
• 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%:
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
Hexa
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
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
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
$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
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
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
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
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
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.
• 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
snappyHexMesh
snappyHexMesh
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
Background mesh Geometry (STL file) Background mesh Geometry (STL file)
snappyHexMesh snappyHexMesh
355 356
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
361 362
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow snappyHexMesh workflow
details. geometry
{
Definition of geometry entities
to be used for meshing
action. castellatedMeshControls
Definition of feature, surface
and volume mesh refinement
$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
... 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;
... ...
... ...
... ...
} }
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.
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
• 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
• 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
• 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
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
...
...
...
...
...
...
• 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.
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
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
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
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
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
407 408
• 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:
...
...
...
Your final mesh should looks like this one
411 412
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
Effect of different parameters on the boundary layer meshing Effect of different parameters on the boundary layer meshing
• 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
• 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
...
...
...
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
);
...
...
...
• 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
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
//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:
• 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
• 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:
Geometry width
FACE 1
• 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
castellatedMeshControls
{
...
...
...
refinementRegions
{
mixing_elbow Name of surface
{
mode distance; Refinement using distance mode
levels ((1e-4 1));
}
}
…
• mixing_elbow_outlet …
• The surface patch pipe was created in the geometry section of the dictionary
snappyHexMeshDict. • mixing_elbow_inlet1 geometry
{
surfacemesh.stl
…
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
$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
• 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.
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
}
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
{
...
...
...
467 468
• 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.
• system/createPatchDict patches
{
The nanme was defined in snappyHexMeshDict
}
}
} The master and slave patches
471 share a common face 472
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
$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
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
485 486
Mesh conversion Mesh conversion
Case 1. Mixing elbow (internal mesh). Case 1. Mixing elbow (internal mesh).
• checkMesh output. • The boundary file.
487 488
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.
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.
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:
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
• structured
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
• 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.
519 520
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
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
• You will find this case in the directory: Experimental values 0.0332 2.167
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
• 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
• 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
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.
• 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
Vectors Vectors
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
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
$PTOFC/postprocessing/supersonic_wedge/
567 568
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
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,
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
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
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
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
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,
• 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,
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.,
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 →
• 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,
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
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 .
• $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
• 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
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
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.
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
647 648
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
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'
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
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 );
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
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
663 664
• 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
671 672
679 680
2. We iterate this many times Unsteady solution residuals Steady solution residuals
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
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.
• 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.
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),
• 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
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;
type zeroGradient;
movingWall movingWall
{ {
type fixedValue;
type fixedValue; type zeroGradient;
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
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.
$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
(0 0 0) (1 0 0)
U = zeroGradient
T = zeroGradient
Initial conditions
U = (1 0 0)
T=0
719 720
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
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
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.
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
• 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
C C
field field
735 736
A B gradSchemes:
A B gradSchemes:
Gauss leastSquares Gauss leastSquares
laplacianSchemes: laplacianSchemes:
Gauss linear orthogonal Gauss linear limited 1
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
Swing:
Flow in a lid-driven square cavity – Re = 100
Effect of grading 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.
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
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.
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
751 752
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
• 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
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
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
#};
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,
• 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
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
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,
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
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
00
00
00
1. codeStream – Highlights
0 02
2. Implementing boundary conditions using
codeStream
0 01
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
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
6. $> paraFoam
if ( pow(y-ke,2) <= ((1 - pow(x-he,2)/pow(ae,2) )*pow(be,2)) )
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
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
• 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
811 812
if (y <= 0.2)
{ Assign value to alpha according to
alpha[i] = 1.; conditional structure
}
}
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
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
819 820
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®
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®
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
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
ogarit mi layer
uffer layer
is ous sublayer inertial s ales
riti al lengt
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.
839 840
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
MODEL
URANS
complexity
Unsteady Reynolds-Averaged Navier-Stokes equations
Cell size
This cell is not resolving the eddies Cell size
This cell may be resolving the eddies DES
SRS
•
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.
Overview of turbulence modeling approaches Short description of some RANS turbulence models
• 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®
If we retain this term, we talk about URANS equations and if we drop it we talk about RANS equations
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
• 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
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
• 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
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
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®
• 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®
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
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
VOF ≈ 0.5
Average phase
properties
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
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
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
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
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®
A crash introduction to multiphase flows modeling OpenFOAM® A crash introduction to multiphase flows modeling OpenFOAM®
• 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
Drag coefficient
Hull position Time (s)
• 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.
}
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)
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
• 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.
• 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
• 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
• 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;
915 916
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 crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®
NSE
Thermal boundary layer vs. Viscous boundary layer Thermal boundary layer in function of Prandtl number (Pr)
Forced convection
A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®
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®
929 930
A crash introduction to compressible flows modeling OpenFOAM® A crash introduction to compressible flows modeling OpenFOAM®
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®
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
• 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
• 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®
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®
• 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.
• 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
$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
951 952
• 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.
• 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
• 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
• 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
$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
• 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
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
973 974
A crash introduction to source terms OpenFOAM® A crash introduction to source terms OpenFOAM®
975 976
• 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
• 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
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.
$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
991
Training material
You can download the training material in the following link:
http://www.wolfdynamics.com/tutorials.html?layout=edit&id=50