Python For Data Science
Python For Data Science
Python For Data Science
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-2018
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
• Courier new • Large code listing, ascii files listing, and screen outputs can be written in
a square box, as follows:
Indicates Linux commands that should be typed literally by the
user in the terminal
1 #include <iostream>
• Courier new bold 2 using namespace std;
3
Indicates directories 4 // main() is where program execution begins. It is the main function.
• Courier new italic 5 // Every program in c++ must have this main function declared
6
Indicates human readable files or ascii files 7 int main ()
8 {
• Arial bold 9 cout << "Hello world"; //prints Hello world
Indicates program elements such as variables, function names, 10 return 0; //returns nothing
11 }
classes, databases, data types, environment variables,
statements and keywords. They also highlight important
information • To improve readability, the text might be colored.
• Arial underline in blue • The font can be Courier new or Arial bold.
Indicates URLs and email addresses • And when required, the line number will be shown.
This icon indicates a warning or a caution • You can extract the training material wherever you want. However, we highly recommend you to extract all the
training material in your OpenFOAM® user directory. From now on, this directory will become,
• $PTOFC
This icon indicates a tip, suggestion, or a general note (abbreviation of Path To OpenFOAM® Course)
This icon indicates that more information is available in the • From now on and whenever you read $PTOFC, it is referring to the location where you extracted the training
material.
referred location
• You can add an alias to $PTOFC in your .bashrc file by adding the following line (remember to source again
This icon indicates a folder or directory the .bashrc file or to open a new terminal after modifying the file),
• alias PTOFC=‘cd PATH_TO_TUTORIALS’
This icon indicates a human readable file (ascii file)
• To uncompress the tutorials go to the directory where you copied the training material and then type in the
terminal,
This symbol indicates that a Linux command should be typed
$> literally by the user in the terminal
• $> tar –zxvf file_name.tar.gz
• A word of caution, use the tutorials included in the training material just for recreational, instructional,
or learning purposes and not for validation, benchmarking or as standard practices.
This icon indicates that the figure is an animation (animated gif)
Training agenda Training agenda
Module 0. Module 3. Module 6. Module 8.
• Training agenda • Meshing preliminaries • The finite volume method. A crash • Advanced modeling capabilities:
• On the training material • Mesh quality assessment introduction • Turbulence modeling
• Housekeeping issues • Meshing in OpenFOAM® – blockMesh and • On the CFL number • Multiphase flows
• Additional information snappyHexMesh • Boundary conditions and initial conditions • Compressible flows
• Mesh conversion and manipulation • Unsteady and steady simulations • Moving reference frames and sliding
Module 1. • Assessing convergence grids
• Introduction to OpenFOAM® Module 4. • Velocity pressure-coupling • Moving bodies and rigid body motion
• A few OpenFOAM® simulations • Running in parallel • Linear solvers • Source terms and passive scalars
• Library organization • Running in the cloud – Amazon EC2
• OpenFOAM® 101 – My first tutorial Module 7. Module 9.
Module 5. • Programming in OpenFOAM® • Conclusions and wrap-up session
Module 2. • Scientific visualization with • Building blocks
ParaView/paraFoam • Implementing/modifying applications
• CFD workflow
• Data conversion • Implementing boundary conditions, initial
• Solid modeling using open source tools • Sampling and plotting conditions and utilities
• Co-processing • codeStream
Training agenda
Provisional timetable
Module 1
OpenFOAM® overview – First tutorial –
Working our way in OpenFOAM®
The above outline is a guide only and every attempt will be made to fulfill the program
1
Roadmap OpenFOAM® brief overview
General description:
1. OpenFOAM® brief overview • OpenFOAM® stands for Open Source Field Operation and Manipulation.
2. OpenFOAM® directory organization • OpenFOAM® is first and foremost a C++ library used to solve partial
differential equations (PDEs), and ordinary differential equations (ODEs).
3. Directory structure of an application/utility
• It comes with several ready-to-use or out-of-the-box solvers, pre-processing
4. Applications/utilities in OpenFOAM® utilities, and post-processing utilities.
5. Directory structure of an OpenFOAM® case • It is licensed under the GNU General Public License (GPL). That means it is
6. Running my first OpenFOAM® case setup blindfold freely available and distributed with the source code.
7. A deeper view to my first OpenFOAM® case setup • It can be used in massively parallel computers. No need to pay for separate
licenses.
8. 3D Dam break – Free surface flow
• It is under active development.
9. Flow past a cylinder – From laminar to turbulent flow
• It counts with a wide-spread community around the world (industry,
academia and research labs).
2 3
4 5
OpenFOAM® brief overview OpenFOAM® brief overview
Under the hood you will find the following: OpenFOAM® vs. Commercial CFD applications:
• Finite Volume Method (FVM) based solver. • OpenFOAM® capabilities mirror those of commercial CFD applications.
• Collocated polyhedral unstructured meshes. • The main differences with commercial CFD applications are:
• Second order accuracy in space and time. Many discretization schemes • There is no native GUI.
available (including high order methods).
• It is not a single executable. Depending of what you are looking for,
• Steady and transient solvers available. you will need to execute a specific application from the command
• Pressure-velocity coupling via segregated methods (SIMPLE and PISO). line interface (CLI).
• But coupled solvers are under active development. • It is not well documented, but the source code is available.
• Massive parallelism through domain decomposition. • Access to complete source = no black magic. But to understand the
source code you need to know object oriented programming and
• It comes with it own mesh generation tools.
C++.
• It also comes with many mesh manipulation and conversion utilities.
• Solvers can be tailored for a specific need, therefore OpenFOAM®
• It comes with many post-processing utilities. is ideal for research and development.
• All components implemented in library form for easy re-use. • It is free.
6 7
8 9
Roadmap OpenFOAM® directory organization
$WM_PROJECT_DIR If you installed OpenFOAM® in the default location, the
1. OpenFOAM® brief overview ├── Allwmake directory the environment variable $WM_PROJECT_DIR
├── applications should point to the following directory (depending on the
2. OpenFOAM® directory organization ├── bin installed version):
10 11
To list all the environment variables related to To list all the aliases related to OpenFOAM®, type in the
OpenFOAM®, type in the terminal: terminal:
$> env | grep “OpenFOAM” $> alias | grep “FOAM”
12 13
OpenFOAM® directory organization OpenFOAM® directory organization
$WM_PROJECT_DIR The applications directory
├── Allwmake Let us study each directory inside $WM_PROJECT_DIR/applications
├── applications ├── Allwmake
├── bin $WM_PROJECT_DIR
├── solvers
├── COPYING ├── test
├── doc └── utilities
├── etc
├── platforms
├── README.org • Any modification you add to the source code in Let us visit the applications directory. Type in the terminal app or
├── src WM_PROJECT_DIR will affect the whole library. $> cd $WM_PROJECT_DIR/applications. You will find the following sub-directories:
├── tutorials • Unless you know what are you doing, do not • solvers, which contains the source code for the distributed solvers.
└── wmake modify anything in the original installation
• test, which contains the source code of several test cases that show the usage of
($WM_PROJECT_DIR), except for updates!
some of the OpenFOAM® classes.
• 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
utilities. To compile the test cases in test go to the desired test case directory and
compile it by typing wmake.
14 15
The directory tree is not complete The directory tree is not complete
20 21
OpenFOAM® directory organization OpenFOAM® directory organization
The tutorials directory The wmake directory
$WM_PROJECT_DIR/tutorials/ Let us visit the tutorials directory. Type in the $WM_PROJECT_DIR/wmake/ Let us visit the wmake directory.
├── Allclean terminal tut or ├── makefiles
├── Allrun $> cd $WM_PROJECT_DIR/tutorials ├── platforms • OpenFOAM® uses a special make
├── Alltest ├── rules command: wmake
├── basic ├── scripts
├── combustion • The tutorials directory contains example ├── src • wmake understands the file structure in
├── compressible cases for each solver. These are the tutorials ├── wclean OpenFOAM® and uses default compiler
├── discreteMethods distributed with OpenFOAM®. ├── wcleanLnIncludeAll directives set in this directory.
├── DNS ├── wcleanPlatform
• They are organized according to the physics • If you add a new compiler name in
├── electromagnetics ├── wdep OpenFOAM® bashrc file, you should also
involved.
├── financial ├── ... tell wmake how to interpret that name. In
├── heatTransfer • Use these tutorials as the starting point to ├── wmake wmake/rules you will find the default
├── incompressible develop you own cases. ├── wmakeFilesAndOptions settings for the available compilers.
├── IO ├── wmakeLnInclude
├── lagrangian • A word of caution, do not use these tutorials ├── wmakeLnIncludeAll • You will also find a few scripts that are
├── mesh as best practices, they are there just to show └── wrmo useful when organizing your files for
├── multiphase how to use the applications. compilation, or for cleaning up.
├── resources
└── stressAnalysis 22
The directory tree is not complete
23
├── $WM_PROJECT_USER_DIR • If you want to locate a directory inside $WM_PROJECT_DIR that contains the string fvPatch in
its name, you can proceed as follows,
└── $WM_PROJECT_DIR • $> find $WM_PROJECT_DIR –type d -name “*fvPatch*”
• When working with OpenFOAM®, you can put your files wherever you want. • If you want to locate a file inside $WM_PROJECT_DIR that contains the string fvPatch in its
• To keep things in order, it is recommended to put your cases in your name, you can proceed as follows,
OpenFOAM® user directory or $WM_PROJECT_USER_DIR. • $> find $WM_PROJECT_DIR –type f -name “*fvPatch*”
• It is also recommended to put your modified solvers, utilities, and libraries in Where to look for Look for Case Look for this
your OpenFOAM® user directory or $WM_PROJECT_USER_DIR. This is done so files sensitive (using wildcards)
you do not modify anything in the original installation. • If you want to find a string inside a file, you can use the grep command.
• If you followed the standard installation instructions, the variable • For example, if you want to find the string LES inside all the files within the directory
$WM_PROJECT_USER_DIR should point to the directory $FOAM_SOLVERS, you can proceed as follows,
$HOME/OpenFOAM/USER_NAME-5.x, where USER_NAME is the name of the • $> grep -r -n “LES” $FOAM_SOLVERS
user (e.g., johnDoe).
The argument -r means recursive and -n will output the line number.
24 25
OpenFOAM® directory organization OpenFOAM® directory organization
Looking for information in OpenFOAM® source code Looking for information in OpenFOAM® source code
• Dictionaries are input files required by OpenFOAM®. • A few more advanced commands to find information in your OpenFOAM® installation.
• As you can imagine, there are many dictionaries in OpenFOAM®. The easiest way to find all of • To find which tutorial files use the boundary condition slip:
them is to do a local search in the installation directory as follows, • $> find $FOAM_TUTORIALS -type f | xargs grep -sl ‘ slip’
• For instance, if you are interested in finding all the files that end with the Dict word in the This command will look for all files inside the directory $FOAM_TUTORIALS, then the
tutorials directory, in the terminal type:
output is used by grep to search for the string slip.
• $> find $FOAM_TUTORIALS -name “*Dict”
(Case sensitive search)
• To find where the source code for the boundary condition slip is located:
• $> find $FOAM_TUTORIALS –iname ‘*dict’
(Non-case sensitive search) • $> find $FOAM_SRC -name “*slip*”
• When given the search string, you can use single quotes ‘ ’ or double-quotes “ ” (do not mixed • To find what applications do not run in parallel:
them). • $> find $WM_PROJECT_DIR -type f | xargs grep -sl ‘noParallel’
• We recommend to use single quotes, but it is up to you.
• OpenFOAM® understands REGEX syntax.
26 27
28 29
Directory structure of an OpenFOAM® application/utility Directory structure of an OpenFOAM® application/utility
The $WM_PROJECT_DIR/applications/solvers/solverName/ directory contains the The $WM_PROJECT_DIR/utilities/utilityName/ directory contains the source code of
source code of the solver. the utility.
• solverName/appName.C: is the actual source code of the solver. • utilityName/utilityName.C: is the actual source code of the application.
• solverName/createFields.H: declares all the field variables and initializes the solution. • utilityName/header_files.H: header files required to compile the application.
• The Make directory contains compilation instructions. • utilityName/utility_dictionary: application’s master dictionary.
• Make/files: names all the source files (.C), it specifies the solverName name and • The Make directory contains compilation instructions.
location of the output file. • Make/files: names all the source files (.C), it specifies the utilityName name
• Make/options: specifies directories to search for include files and libraries to link the and location of the output file.
solver against. • Make/options: specifies directories to search for include files and libraries to link the
30 solver against. 31
32 33
Applications/utilities in OpenFOAM® Applications/utilities in OpenFOAM®
• OpenFOAM® is not a single executable. • You will find all the applications in the directory $FOAM_SOLVERS (use alias sol to
• Depending of what you want to do, you will need to use a specific application and go there).
there are many of them. • You will find all the utilities in the directory $FOAM_UTILITIES (use alias util to go
• If you are interested in knowing all the solvers, utilities, and libraries that come with there).
your OpenFOAM® distribution, read the applications and libraries section in the user • For example, in the directory $FOAM_SOLVERS, you will find the directories containing
guide (chapter 3). In the directory $WM_PROJECT_DIR/doc you will find the the source code for the solvers available in the OpenFOAM® installation (version
documentation in pdf format. 5.x):
• You can also access the online user guide. Go to the link
http://cfd.direct/openfoam/user-guide/#contents, then go to chapter 3 • basic • financial
(applications and libraries). • combustion • heatTransfer
• If you want to get help on how to run an application, type in terminal • compressible • incompressible
• discreteMethods • lagrangian
1. $> application_name -help • DNS • multiphase
• electromagnetics • stressAnalysis
• The option –help will not run the application, it will only show all the options
available. • The solvers are subdivide according to the physics they address.
• You can also get all the help you want from the source code. • The utilities are also subdivided in a similar way.
34 35
36 37
Roadmap Directory structure of an OpenFOAM® case
Directory structure of a general case
1. OpenFOAM® brief overview case_name • OpenFOAM® uses a very particular directory
├── 0 structure for running cases.
2. OpenFOAM® directory organization
│ ├── p • You should always follow the directory structure,
3. Directory structure of an application/utility │ └── U otherwise, OpenFOAM® will complain.
├── constant • To keep everything in order, the case directory is
4. Applications/utilities in OpenFOAM® │ ├── polyMesh often located in the path
$WM_PROJECT_USER_DIR/run.
│ │ ├── boundary
5. Directory structure of an OpenFOAM® case │ │ ├── faces • This is not compulsory but highly advisable. You can
copy the case files anywhere you want.
6. Running my first OpenFOAM® case setup blindfold │ │ ├── neighbour
• The name of the case is given by the user (do not
│ │ ├── owner use white spaces or strange symbols).
7. A deeper view to my first OpenFOAM® case setup │ │ └── points
• Depending of the solver or application you would like
│ └── transportProperties
8. 3D Dam break – Free surface flow ├── system
to use, you will need different files in each sub-
directory.
9. Flow past a cylinder – From laminar to turbulent flow │ ├── controlDict • Remember, you always run the applications and
│ ├── fvSchemes utilities in the top level of the case directory (the
│ └── fvSolution directory with the name case_name). Not in the
directory system, not in the directory constant, not
└── time_directories in the directory 0.
38 39
40 41
Roadmap Running my first OpenFOAM® case setup blindfold
Before we start – Simulation workflow – Generic global view
1. OpenFOAM® brief overview
GEOMETRY
2. OpenFOAM® directory organization
3. Directory structure of an application/utility
4. Applications/utilities in OpenFOAM®
MESH
5. Directory structure of an OpenFOAM® case
6. Running my first OpenFOAM® case setup blindfold
7. A deeper view to my first OpenFOAM® case setup
SOLVER CO-PROCESSING
8. 3D Dam break – Free surface flow
9. Flow past a cylinder – From laminar to turbulent flow
POST-PROCESSING
42 43
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Before we start – Always remember the directory structure Before we start – Setting OpenFOAM® cases
case_name
• As you will see, it is quite difficult to remember all the dictionary files needed to run
├── 0
each application.
├── constant
│ └── polyMesh • It is even more difficult to recall the compulsory and optional entries of each input file.
├── system • When setting a case from scratch in OpenFOAM®, what you need to do is find a
└── time_directories tutorial or a case that close enough does what you want to do and then you can adapt
it to your physics.
• To keep everything in order, the case directory is often located in the path
$WM_PROJECT_USER_DIR/run. This is not compulsory but highly advisable, you can put • Having this in mind, you have two sources of information:
the case in any directory of your preference. • $WM_PROJECT_DIR/tutorials
• The name of the case directory if given by the user (do not use white spaces). (The tutorials distributed with OpenFOAM®)
• You run the applications and utilities in the top level of this directory. • $PTOFC
(The tutorials used during this training)
• The directory system contains run-time control and solver numerics.
• The directory constant contains physical properties, turbulence modeling properties,
• If you use a GUI, things are much easier. However, OpenFOAM® does not come
advanced physics and so on. with a native GUI interface.
• The directory constant/polyMesh contains the polyhedral mesh information. • We are going to do things in the hard way (and maybe the smart way), we are going
• The directory 0 contains boundary conditions (BC) and initial conditions (IC). to use the Linux terminal
44 45
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Flow in a lid-driven square cavity – Re = 100 Workflow of the case
Incompressible flow
46 47
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
At the end of the day, you should get something like this At the end of the day, you should get something like this
Y centerline
Pressure field (relative pressure) Velocity magnitude field High-Re Solutions for incompressible flow using the navier-stokes equations and a multigrid method
U. Ghia, K. N. Ghia, C. T. Shin.
48 Journal of computational physics, 48, 387-411 (1982) 49
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Loading OpenFOAM® environment
• If you are using our virtual machine or using the lab workstations, you will need to
source OpenFOAM® (load OpenFOAM® environment).
• Let us run our first case. Go to the directory:
• To source OpenFOAM®, type in the terminal:
• $> of5x
$PTOFC/101OF/cavity2D
• To use PyFoam you will need to source it. Type in the terminal:
• $> anaconda2 or $> anaconda3
• From this point on, please follow me. • Remember, every time you open a new terminal window you need to source
OpenFOAM® and PyFoam.
• We are all going to work at the same pace.
• Remember, $PTOFC is pointing to the path where you • By default, when installing OpenFOAM® and PyFoam you do not need to do this.
unpacked the tutorials. This is our choice as we have many things installed and we want to avoid conflicts
between applications.
50 51
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
What are we going to do? Running the case blindfold
• We will use the lid-driven square cavity tutorial as a general example to show you • Let us run this case blindfold.
how to set up and run solvers and utilities in OpenFOAM®. • Later we will study in details each file and directory.
• In this tutorial we are going to generate the mesh using blockMesh. • Remember, the variable $PTOFC is pointing to the path where you unpacked the
• After generating the mesh, we will look for topological errors and assess the mesh tutorials.
quality. For this we use the utility checkMesh. Later on, we are going to talk about • You can create this environment variable or write down the path to the directory.
what is a good mesh. • In the terminal window type:
• Then, we will find the numerical solution using icoFoam, which is a transient solver
1. $> cd $PTOFC/101OF/cavity
for incompressible, laminar flow of Newtonian fluids. By the way, we hope you did not
forget where to look for this information. 2. $> ls –l
• And we will finish with some cool visualization and post-processing using paraFoam. 3. $> blockMesh
• While we run this case, we are going to see a lot of information on the screen 4. $> checkMesh
(standard output stream or stdout), but it will not be saved. This information is mainly $> icoFoam
5.
related to convergence of the simulation, we will talk about this later on.
6. $> postProcess -func sampleDict -latestTime
7. $> gnuplot gnuplot/gnuplot_script
8. $> paraFoam
52 53
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Running the case blindfold Crash introduction to paraFoam
• In step 1 we go to the case directory. Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
Menu Bar
• In step 2 we just list the directory structure. Does it look familiar to you? In the directory 0 you
Toolbars
will the initial and boundary conditions, in the constant directory you will find the mesh
information and physical properties, and in the directory system you will find the dictionaries
Pipeline Browser
that controls the numerics, runtime parameters and sampling.
• In step 3 we generate the mesh.
• In step 4 we check the mesh quality. We are going to address how to assess mesh quality later Properties panel
on.
• In step 5 we run the simulation. This will show a lot information on the screen, the standard
output stream will not be saved.
• In step 6 we use the utility postProcess to do some sampling only of the last saved solution. Apply button
Press this button to
This utility will read the dictionary file named sampleDict located in the directory system.
load the case or to
• In step 7 we use a gnuplot script to plot the sampled values. Feel free to take a look and reuse apply a filter
this script.
• Finally, in step 8 we visualize the solution using paraFoam. In the next slides we are going to
briefly explore this application.
3D View/Canvas
Advanced Toggle
54 55
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Toolbars Crash introduction to paraFoam – Mesh visualization
Select Surface With Edges in the Representation Toolbar Fit to screen Select the -Z view
• Main Controls
Select Solid Color in the
Active Variable Controls
• VCR Controls (animation controls)
• Representation Toolbar
Rotate
Select Surface in the
Representation Toolbar
Pan
Zoom
Select volume fields to visualize.
By default it will select U and p.
3D View/Canvas
58 59
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Filters Crash introduction to paraFoam – Filters
• Filters are functions that generate, extract or derive features from the input data.
• They are attached to the input data.
• You can access the most commonly used filters from the Common Filters toolbar
Filters are attached
to the input data
• You can access all the filters from the menu Filter.
60 61
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Slice filter Crash introduction to paraFoam – Glyph filter
4. Color the colors using Solid Color
1. Select the Slice filter 1. Select the Glyph filter. This
filter will be applied on the
Slice1 filter
62 63
Running my first OpenFOAM® case setup blindfold Running my first OpenFOAM® case setup blindfold
Crash introduction to paraFoam – Plot Over Line filter Crash introduction to paraFoam – Filters
4. Optional – Use the VCR Control to change the frame.
1.a. Select the Plot Over Line The line chart view will be updated automatically
filter.
3. Press Apply
Line 1. Click on the line chart view (the blue frame indicates that it is the active view)
64 65
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
• In the previous case, we ran the simulation but we did not save the standard output • There are many ways to save the log files.
stream (stdout) in a log file. • From now on, we will use the Linux tee command to save log files.
• We just saw the information on-the-fly. • To save a log file of the simulation, you can proceed as follows:
• Our advice is to always save the standard output stream (stdout) in a log file. $> foamCleanTutorials
1.
• It is of interest to always save the log as if something goes wrong and you would like 2. $> foamCleanPolyMesh
to do troubleshooting, you will need this information. 3. $> blockMesh
• Also, if you are interested in plotting the residuals you will need the log file. 4. $> checkMesh
5. $> icoFoam | tee log.icoFoam
• By the way, if at any point you ask us what went wrong with your simulation, we will
ask you for this file.
• We might also ask for the standard error stream (stderr). Vertical bar or pipelining operator, used to
concatenate commands
• You can use your favorite text editor to read the log file (e.g., gedit, vi, emacs).
66 67
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
• In steps 1 and 2 we erase the mesh and all the folders, except for 0, constant and • To plot the information extracted with foamLog using gnuplot, we can proceed as
system. These scripts come with your OpenFOAM® installation. follows (remember, at this point we are using the gnuplot prompt):
• In step 3, we generate the mesh using the meshing tool blockMesh. 1. gnuplot> set logscale y
Set log scale in the y axis
• In step 4 we check the mesh quality.
2. gnuplot> plot ‘logs/p_0’ using 1:2 with lines
• In step 5 we run the simulation. Hereafter, we redirect the standard output to an ascii Plot the file p_0 located in the directory logs, use columns 1 and 2 in the file p_0, use lines to output the plot.
file with the name log.icoFoam (it can be any name). The tee command will
3. gnuplot> plot ‘logs/p_0’ using 1:2 with lines, ‘logs/pFinalRes_0’ using 1:2 with lines
redirect the screen output to the file log.icoFoam and at the same time will show Here we are plotting to different files. You can concatenate files using comma (,)
68 69
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 and plotting the residuals
• The output of step 3 is the following: • It is also possible to plot the log information on the fly.
• The easiest way to do this is by using PyFoam (you will need to install it):
• $> pyFoamPlotRunner.py [options] <foamApplication>
• If you are using our virtual machine or using the lab workstations, you will need to
source PyFoam.
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
• To run this case with pyFoamPlotRunner.py, in the terminal type: • This is a screenshot on my computer. In this case, pyFoamPlotRunner is plotting
• $> pyFoamPlotRunner.py icoFoam the initial residuals and continuity errors on the fly.
• You can also use pyFoamPlotWatcher.py to plot the information saved in an old
log file.
72 73
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: 5.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: 5.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;
74 75
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: 5.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: 5.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
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
76 77
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,
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
78 79
80 81
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: 5.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 }
82 83
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.
86 87
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 now take a quick look at the blockMeshDict dictionary in order to
• Also, depending of your physical model, you will find more dictionaries in the constant understand what we have done. Do not worry, we are going to revisit this dictionary
directory. during the meshing session.
• For example, if you need to set gravity, you will need to create the dictionary g. • Go to the directory system and open blockMeshDict dictionary with your favorite
text editor, we will use gedit.
• If you work with compressible flows you will need to define the dynamic viscosity mu,
and many other physical properties in the dictionary thermophysicalProperties.
• As we are not dealing with compressible flows (for the moment), we are not going into
details.
88 89
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 then defines a block from the vertices:
• The keyword convertToMeters (line 17), is a scaling factor. In this case
17 convertToMeters 1;
18
we do not scale the dimensions.
19 xmin 0;
20 xmax 1; • In the section vertices (lines 37-58), we define the vertices coordinates of 60 blocks
21 ymin 0; the geometry. In this case, there are eight vertices defining the geometry. 61 (
22 ymax 1;
23 zmin 0;
OpenFOAM® always uses 3D meshes, even if the simulation is 2D. 62 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
24 zmax 1;
• We can directly define the vertex coordinates in the section vertices 63 );
25
26 xcells 20; (commented lines 49-56), or we can use macro syntax.
27 ycells 20;
28 zcells 1; • Using macro syntax we first define a variable and its value (lines 19-24),
29
37 vertices and then we can use them by adding the symbol $ to the variable name
38 ( (lines 39-46).
39 ($xmin $ymin $zmin) //vertex 0 • In lines 60-63, we define the block topology, hex means that it is a
40 ($xmax $ymin $zmin) //vertex 1 • In lines 26-28, we define a set of variables that will be used at a later time. structured hexahedral block. In this case, we are generating a
41 ($xmax $ymax $zmin) //vertex 2
42 ($xmin $ymax $zmin) //vertex 3 rectangular mesh.
43 ($xmin $ymin $zmax) //vertex 4
• Finally, notice that the vertex numbering starts from 0 (as the counters in
44 ($xmax $ymin $zmax) //vertex 5 c++). This numbering applies for blocks as well. • (0 1 2 3 4 5 6 7) are the vertices used to define the block topology
45 ($xmax $ymax $zmax) //vertex 6 (and yes, the order is important). Each hex block is defined by eight
46 ($xmin $ymax $zmax) //vertex 7
47 vertices, in sequential order. Where the first vertex in the list
48 /* represents the origin of the coordinate system.
49 (0 0 0)
50 (1 0 0) • ($xcells $ycells $zcells) is the number of mesh cells in each
51 (1 1 0)
52 (0 1 0) direction (X Y Z). Notice that we are using macro syntax, which is
53 (0 0 0.1) equivalent to (20 20 1).
54 (1 0 0.1)
55 (1 1 0.1) • simpleGrading (1 1 1) is the expansion ratio or mesh stretching in
56 (0 1 0.1)
57 */ each direction (X Y Z), in this case the mesh is uniform.
58 );
90 91
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 then defines a block from the vertices: • The blockMeshDict dictionary also defines edges:
65 edges
66 (
67 //arc 0 1 (0.5 -0.1 0)
68 //arc 4 5 (0.5 -0.1 1)
69 );
• Let us talk about the block ordering hex (0 1 2 3 4 5 6 7), which is extremely important. • The user can specified any edge to be curved by entries in the block edges.
• hex blocks are defined by eight vertices in sequential order. Where the first vertex in the list represents the • Possible options are: arc, spline, polyline, BSpline, line.
origin of the coordinate system (vertex 0 in this case). • For example, to define an arc we first define the vertices to be connected to form an edge and then we give an
• Starting from this vertex, we construct the block topology. So in this case, the first part of the block is made up interpolation point.
by vertices 0 1 2 3 and the second part of the block is made up by vertices 4 5 6 7. • In this case and as we do not specified anything, all edges are assumed to be straight lines.
• In this case, the vertices are ordered in such a way that if we look at the screen/paper (-Z direction), the • By the way, lines 67 and 68 are commented.
vertices rotate counter-clockwise.
92 93
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 also defines the boundary patches: • The blockMeshDict dictionary also defines the boundary patches:
• In the section boundary, we define all the surface • We can also group many faces into one patch, for
71 boundary 71 boundary
72 ( patches where we want to apply boundary conditions. 72 ( example, take a look at lines 86-88. In this case:
73 movingWall Name 73 movingWall
74 { • This step is of paramount importance, because if we do 74 { • The name of the patch is fixedWalls
75 type wall; Type 75 type wall;
not define the surface patches we will not be able to
76 faces 76 faces
• The base type is wall
77 (
Connectivity
apply the boundary conditions. 77 (
78 (3 7 6 2) 78 (3 7 6 2)
79 ); 79 ); • The surface patch is made up by the faces
• For example:
80
81
}
fixedWalls
80
81
}
fixedWalls
(0 4 7 3), (2 6 5 1), and (1 5 4 0).
82 { • In line 73 we define the patch name movingWall 82 {
83 type wall; 83 type wall; • The base type empty (line 93) is used to define a 2D
(the name is given by the user).
84
85
faces
(
84
85
faces
(
mesh. There is only one cell in the direction of the vector
86 (0 4 7 3) • In line 75 we give a base type to the surface patch. 86 (0 4 7 3) connecting faces (0 3 2 1) and (4 5 6 7).
87 (2 6 5 1) 87 (2 6 5 1)
88 (1 5 4 0) In this case wall (do not worry we are going to talk 88 (1 5 4 0)
• If you do not define a boundary patch, it will be
89 );
about this later on). 89 );
90 } 90 } automatically grouped in the patch defaultFaces of type
91 frontAndBack 91 frontAndBack
92 { • In line 78 we give the connectivity list of the 92 { empty.
93 type empty;
vertices that made up the surface patch or face, 93 type empty;
94 faces 94 faces • The name and type of the surface patch can be changed
95 ( that is, (3 7 6 2). Have in mind that the vertices 95 (
96 (0 3 2 1) 96 (0 3 2 1) outside of the blockMeshDict, we are going to address
need to be neighbors and it does not matter if the
97 (4 5 6 7) 97 (4 5 6 7)
this later.
98
99 }
);
ordering is clockwise or counter clockwise. 98
99 }
);
100 ); 100 );
• Remember, faces are defined by a list of 4 vertex
numbers, e.g., (3 7 6 2).
94 95
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 also defines how to merge multiple blocks: • To sum up, the blockMeshDict dictionary generates a single block with:
• X/Y/Z dimensions: 1.0/1.0/1.0
102 mergePatchPairs • Cells in the X, Y and Z directions: 20 x 20 x 1 cells.
103 (
104 //(interface1 interface2)
• One single hex block with straight lines.
105 );
96 97
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The system/blockMeshDict dictionary The constant/polyMesh/boundary dictionary
• As you can see, the blockMeshDict dictionary can be really tricky. • First at all, this file is automatically generated after you create the mesh
• If you deal with really easy geometries (rectangles, cylinders, and so on), then you using blockMesh or snappyHexMesh, or when you convert the mesh from
can use blockMesh to do the meshing, but this is the exception rather than the rule. a third-party format.
• When using snappyHexMesh, (a body fitted mesher that comes with OpenFOAM®) • In this file, the geometrical information related to the base type patch of
you will need to generate a background mesh using blockMesh. We are going to each boundary (or surface patch) of the domain is specified.
deal with this later on.
• The base type boundary condition is the actual surface patch where we are
• Our best advice is to create a template and reuse it until the end of the world. going to apply a primitive type boundary condition (or numerical boundary
• Also, take advantage of macro syntax for parametrization, and #calc syntax to condition).
perform inline calculations (lines 30-35 in the blockMeshDict dictionary we just
• The primitive type boundary condition assign a field value to the surface
studied).
patch (base type).
• We are going to deal with #codeStream syntax and #calc syntax during the
programming session. • You define the primitive type patch (or the value of the boundary condition),
in the directory 0 or time directories.
The mesher blockMesh has many more features that we did not address in
this short overview. Refer to the User Guide for more Information.
98 99
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
100 101
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
19 ( inGroups keyword 19 (
20 movingWall 20 movingWall
21 { 21 {
22 type wall; • This keyword is optional. You can erase this 22 type wall;
23 inGroups 1(wall); 23 inGroups 1(wall);
24 nFaces 20; information safely. 24 nFaces 20; nFaces and startFace keywords
25 startFace 760; 25 startFace 760;
26 } • It is used to group patches during visualization 26 }
27 fixedWalls in ParaView/paraFoam. If you open this mesh 27 fixedWalls • Unless you know what you are
28 { 28 {
29 type wall;
in paraFoam you will see that there are two 29 type wall;
doing, you do not need to modify
30 inGroups 1(wall); groups, namely: wall and empty. 30 inGroups 1(wall); this information.
31 nFaces 60; 31 nFaces 60;
32 startFace 780; • As usual, you can change the name. 32 startFace 780; • Basically, this is telling you the
33 } 33 } starting face and ending face of the
34 frontAndBack • If you want to put a surface patch in two 34 frontAndBack
35 { 35 { patch.
36 type empty;
groups, you can proceed as follows: 36 type empty;
37 inGroups 1(empty); 37 inGroups 1(empty); • This is created automatically when
2(wall wall1)
38 nFaces 800; 38 nFaces 800; generating the mesh or converting
39 startFace 840; 39 startFace 840;
40 }
In this case the surface patch belongs to the 40 }
the mesh.
41 ) groups wall and wall1. 41 )
102 103
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 primitive 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 primitive 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 primitive type of the patches (the empty empty
patch type defined in the field files contained in the directory 0 (or whatever time directory you
wedge wedge
defined the boundary and initial conditions).
cyclic cyclic
• If the base type and primitive type boundary conditions are not consistent, OpenFOAM® will
complain. processor processor
• Do not worry, we are going to address boundary conditions later on.
104 105
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 primitive or derived type boundary • The wall base type boundary condition is defined as follows:
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.
106 107
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:
primitive 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.
108 109
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
as, start time, end time, time step, saving frequency and so on.
• So how do we know what options are available for each keyword?
17 application icoFoam; • Most of the entries are self-explanatory. 17 application icoFoam;
18 18 • The hard way is to refer to the source code.
19 startFrom startTime; • This case starts from time 0 (keyword startFrom – line 19 – and 19 startFrom startTime;
20
21 startTime 0; keyword startTime – line 21 –). If you have the initial solution in a
20
21 startTime 0;
• The easy way is to use the banana method.
22 different time directory, just enter the number in line 21. 22
23 stopAt endTime; 23 stopAt banana; • So what is the banana method? This method consist in inserting a
24
25 endTime 50;
• The case will stop when it reaches the desired time set using the keyword 24
25 endTime 50; dummy word (that does not exist in the installation) and let
26 stopAt (line 23). 26 OpenFOAM® list the available options.
27 deltaT 0.01; 27 deltaT 0.01;
28 • It will run up to 50 seconds (keyword endTime – line 25 –). 28
• For example. If you add banana in line 23, you will get this output:
29 writeControl runTime; 29 writeControl runTime;
30 30
31 writeInterval 1; • The time step of the simulation is 0.01 seconds (keyword deltaT 31 writeInterval 1; banana is not in enumeration
32 – line 27 –). 32 4
33 purgeWrite 0; 33 purgeWrite 0;
34
• It will write the solution every second (keyword writeInterval – line 31 –) 34 (
35 writeFormat ascii; 35 writeFormat ascii;
36 of simulation time (keyword runTime – line 29 –). 36 nextWrite
37 writePrecision 8; 37 writePrecision 8; writeNow
38 • It will keep all the solution directories (keyword purgeWrite – line 33 –). 38
39 writeCompression off; 39 writeCompression off; noWriteNow
If you want to keep only the last 5 solutions just change the value to 5.
40
41 timeFormat general;
40
41 timeFormat general;
endTime
42 • It will save the solution in ascii format (keyword writeFormat – line 35 –) 42 )
43 timePrecision 6; 43 timePrecision 6;
44
with a precision of 8 digits (keyword writePrecision – line 37 –). 44
45 runTimeModifiable true; 45 runTimeModifiable true;
• And as the option runTimeModifiable (line 45) is on (true), we can • So your options are nextWrite, writeNow, noWriteNow, endTime
modify all these entries while we are running the simulation.
• FYI, you can modify the entries on-the-fly for most of the dictionaries files.
110 111
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The controlDict dictionary The controlDict dictionary
• And how do we know that banana does not exist in the source code? • If you forget a compulsory keyword, OpenFOAM® will tell you what
17 application icoFoam; 17 application icoFoam;
are you missing.
18 • Just type in the terminal: 18
19 startFrom startTime; 19 startFrom startTime;
20
• $> src 20 • So if you comment line 25, you will get this output:
21 startTime 0; 21 startTime 0;
22 22
23 stopAt banana; • $> grep –r –n banana . 23 stopAt endTime;
24 24 --> FOAM FATAL IO ERROR
25 endTime 50; 25 //endTime 50;
26 26 keyword endTime is undefined in dictionary …
27 deltaT 0.01; 27 deltaT 0.01;
28 • If you see some bananas in your output someone is messing around 28
29 writeControl runTime;
with your installation. 29 writeControl runTime;
30 30 • This output is just telling you that you are missing the keyword
31 writeInterval 1; 31 writeInterval 1;
32 • You can use the same command to look for information in the 32 endTime.
33
34
purgeWrite 0;
OpenFOAM® installation, just replace the word banana for the word 33
34
purgeWrite 0;
112 113
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The fvSchemes dictionary The fvSolution dictionary
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The fvSolution dictionary The system directory
(optional dictionary files)
39 }
iterations (optional entry).
40
41 pFinal • FYI, solving for the velocity is relative inexpensive, whereas
42
43
{
$p;
solving for the pressure is expensive.
• decomposeParDict is read by the utility decomposePar. This dictionary
44 relTol 0;
45 } • The PISO sub-dictionary contains entries related to the
46
pressure-velocity coupling method (the PISO method).
47
48
U
{
file contains information related to the mesh partitioning. This is used when
• In this case we are doing only one PISO correction and no
49
50
solver
smoother
smoothSolver;
symGaussSeidel;
orthogonal corrections.
running in parallel. We will address running in parallel later.
51 tolerance 1e-08;
52 relTol 0;
53
54 }
} • You need to do at least one PISO loop (nCorrectors). • sampleDict is read by the utility postProcess. This utility sample field
55
56 PISO data (points, lines or surfaces). In this dictionary file we specify the sample
location and the fields to sample. The sampled data can be plotted using
57 {
58 nCorrectors 1;
59 nNonOrthogonalCorrectors 0;
60
61
pRefCell
pRefValue
0;
0;
gnuplot or Python.
62 }
116 117
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The sampleDict dictionary The sampleDict dictionary
Type of sampling, sets will sample along a line.
The sampled information is always saved in the
Format of the output file, raw format is a generic format directory,
17 type sets; that can be read by many applications. The output file is 17 type sets;
18
human readable (ascii format). 18 postProcessing/name_of_input_dictionary
19 setFormat raw; 19 setFormat raw;
20 20
23 interpolationScheme cellPointFace; Interpolation method at the solution level (location of the 23 interpolationScheme cellPointFace;
24 24
26 fields interpolation points). 26 fields As we are sampling the latest time solution (50) and
27 ( 27 (
28 U Fields to sample. 28 U using the dictionary sampleDict, the sampled data
29 ); 29 );
30 30 will be located in the directory:
31 sets 31 sets
32
33
(
Sample method. How to interpolate the solution to the
32
33
(
postProcessing/sampleDict/50
34
35
l1
{
sample entity (line in this case) 34
35
l1
{
36 type midPointAndFace; 36 type midPointAndFace;
43 axis x; 43 axis x;
44 start ( -1 0.5 0); Location of the sample line. We define start and end 44 start ( -1 0.5 0); The files l1_U.xy and l2_U.xy located in the
45
46 }
end ( 2 0.5 0); point, and the axis of the sampling. 45
46 }
end ( 2 0.5 0);
directory postProcessing/sampleDict/50
47
48 l2
47
48 l2 contain the sampled data. Feel free to open them using
49 { 49 {
your favorite text editor.
50
54
type
axis
midPointAndFace;
y;
Sample method from the solution to the line. 50
54
type
axis
midPointAndFace;
y;
55 start (0.5 -1 0); 55 start (0.5 -1 0);
56 end (0.5 2 0); 56 end (0.5 2 0);
57 } 57 }
58 58 Name of the output file
59 );
Location of the sample line. We define start and end 59 );
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 vector): in this case p and U. The U file contains the following information (velocity):
17 dimensions [0 1 -1 0 0 0 0]; Dimensions of the field 17 dimensions [0 1 -1 0 0 0 0]; Dimensions of the field
18 18
19 internalField uniform (0 0 0); 19 internalField uniform (0 0 0);
20 20
21 boundaryField 21 boundaryField
22 { 22 {
23 movingWall 23 movingWall
24 { Uniform initial conditions. 24 {
25 type fixedValue; 25 type fixedValue; Numerical boundary condition for the patch
26 value uniform (1 0 0); The velocity field is initialize to (0 0 0) in all 26 value uniform (1 0 0); movingWall
27 } 27 }
the domain
28 28
29 fixedWalls Remember velocity is a vector with three 29 fixedWalls
30 { 30 {
31 type fixedValue; components, therefore the notation (0 0 0). 31 type fixedValue; Numerical boundary condition for the patch
32 value uniform (0 0 0); 32 value uniform (0 0 0); fixedWalls
33 } 33 }
34 34
35 frontAndBack Note: 35 frontAndBack
If you take some time and compare the files 0/U and
36 { 36 {
37 type empty;
constant/polyMesh/boundary, you will see that the name and type of each
37 type empty;
Numerical boundary condition for the patch
primitive 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). 38 } frontAndBack (this is a constrained boundary
39 } 39 } condition).
120 121
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 p file contains the following information (modified pressure): in this case p and U. The p file contains the following information (modified pressure):
17 dimensions [0 2 -2 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; 19 internalField uniform 0;
20 20
21 boundaryField 21 boundaryField
22 { 22 {
23 movingWall 23 movingWall
24 { Uniform initial conditions. 24 {
Numerical boundary condition for the patch
25 type zeroGradient; 25 type zeroGradient;
26 } The modified pressure field is initialize to 0 26 } movingWall
27 27
in all the domain. This is relative
28 fixedWalls 28 fixedWalls
29 { pressure. 29 {
30 type zeroGradient; 30 type zeroGradient;
Numerical boundary condition for the patch
31 } 31 } fixedWalls
32 32
33 frontAndBack 33 frontAndBack
34 { 34 {
35 type empty; Note: 35 type empty;
Numerical boundary condition for the patch
If you take some time and compare the files 0/p and frontAndBack (this is a constrained boundary
36 } 36 }
constant/polyMesh/boundary, you will see that the name and type of each
37 }
primitive type patch (the patch defined in 0/p), is consistent with the base
37 } condition).
38 type patch (the patch defined in the file constant/polyMesh/boundary). 38
122 123
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
A very important remark on the pressure field dictionaries (e.g. U, p).
• In the header of your field variables, the class type should be consistent with the type
• We just used icoFoam which is an incompressible solver. of field variable you are using.
• Let us be really loud on this. All the incompressible solvers implemented in OpenFOAM® • If the field variable is a scalar, the class should be volScalarField.
(icoFoam, simpleFoam, pisoFoam, and pimpleFoam), use the modified pressure, that is,
124 125
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 • Coming back to the headers, and specifically the headers related to the field variable
dictionaries (e.g. U, p). dictionaries (e.g. U, p).
• In the header of your field variables, the class type should be consistent with the type • In the header of your field variables, the class type should be consistent with the type
of field variable you are using. of field variable you are using.
• If the field variable is a vector, the class should be volVectorField. • If the field variable is a tensor (e.g. the velocity gradient tensor), the class should be
volTensorField.
126 127
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
The log.icoFoam file The log.icoFoam file
• In this case, pyFoamPlotWatcher is plotting the initial residuals, continuity errors
• If you followed the previous instructions you should now have the log.icoFoam file.
and courant number.
This file contains all the residuals and convergence information.
• Let us plot this information again but this time using PyFoam, in the terminal type:
• $> pyFoamPlotWatcher.py log.icoFoam -–with-courant
• The script pyFoamPlotWatcher.py will plot the information in the log file, even if
the simulation is not running.
• The option -–with-courant will plot the courant number.
• Remember, to use PyFoam you will need to source it. Type in the terminal:
• $> anaconda2 or $> anaconda3
128 129
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
53
Courant number 54 minmaxdomain
Pressure residuals 55 {
No orthogonal corrections 56 type fieldMinMax; functionObject to use
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;
End of the simulation Minimum and maximum values of each field 65 writeInterval 1; Output interval of functionObject
66
67 log true; Save output of the functionObject in a ascii file
68
69 fields (p U); Field variables to sample
70 }
91
92 };
130 131
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 easiest way is by
changing the time step).
• The Courant number imposes the CFL number condition, which is the maximum allowable
• For a time step of 0.01 seconds, this is the output we get,
CFL number a numerical scheme can use. For the n - dimensional case, the CFL number
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. 132 133
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 (the easiest way is by • 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). changing the time step).
• For a time step of 0.1 seconds, this is the output we get, • For a time step of 0.5 seconds, this is the output we get,
134 135
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-3), 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: 5.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
136 137
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 : 5.x-5d8318b22cbe
Exec : icoFoam
Date
Time
: Nov 02 2014
: 00:33:41 “Experience 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/5x/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
138 139
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Error output
• Missing keyword class in file p • Mismatching patch name in file p
file: /home/joegi/my_cases_course/5x/101OF/cavity/0/p from line 10 to line 13. file: /home/joegi/my_cases_course/5x/101OF/cavity/0/p.boundaryField from line 25 to line 35.
From function dictionary::lookupEntry(const word&, bool, bool) const From function GeometricField<Type, PatchField, GeoMesh>::GeometricBoundaryField::readField(const
in file db/dictionary/dictionary.C at line 442. DimensionedField<Type, GeoMesh>&, const dictionary&)
in file /home/joegi/OpenFOAM/OpenFOAM-5.x/src/OpenFOAM/lnInclude/GeometricBoundaryField.C at line 209.
FOAM exiting
FOAM exiting
140 141
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Error output
• Missing entry in file fvSolution at keyword PISO • Missing keyword deltaT in file controlDict
--> FOAM FATAL IO ERROR:
"ill defined primitiveEntry starting at keyword 'PISO' on line 68 and ending at line 68" --> FOAM FATAL IO ERROR:
keyword deltaT is undefined in dictionary "/home/joegi/my_cases_course/5x/101OF/cavity/system/controlDict"
file: /home/joegi/my_cases_course/5x/101OF/cavity/system/fvSolution at line 68.
file: /home/joegi/my_cases_course/5x/101OF/cavity/system/controlDict from line 17 to line 69.
From function primitiveEntry::readEntry(const dictionary&, Istream&)
in file lnInclude/IOerror.C at line 132. From function dictionary::lookupEntry(const word&, bool, bool) const
in file db/dictionary/dictionary.C at line 442.
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
• Unknown boundary condition type. • This one is specially hard to spot
FOAM exiting
• Instead of cavity 0 you should use cavity_0.
144 145
A deeper view to my first OpenFOAM® case setup A deeper view to my first OpenFOAM® case setup
Error output Dictionary files general features
• You should worry about the SIGFPE error signal. This error signal indicates that something
went really wrong (erroneous arithmetic operation). • OpenFOAM® follows same general syntax rules as in C++.
• This message (that seems a little bit difficult to understand), is giving you a lot information. • Commenting in OpenFOAM® (same as in C++):
• For instance, this output is telling us that the error is due to SIGFPE and the class associated to
the error is lduMatrix. It is also telling you that the GAMGSolver solver is the affected one
// This is a line comment
(likely the offender is the pressure).
#0 Foam::error::printStack(Foam::Ostream&) at ??:? /*
#1 Foam::sigFpe::sigHandler(int) at ??:?
#2 in "/lib64/libc.so.6" This is a block comment
#3 Foam::DICPreconditioner::calcReciprocalD(Foam::Field<double>&, Foam::lduMatrix const&) at ??:?
#4 Foam::DICSmoother::DICSmoother(Foam::word const&, Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double> */
const&, Foam::FieldField<Foam::Field, double> const&, Foam::UPtrList<Foam::lduInterfaceField const> const&) at ??:?
#5 Foam::lduMatrix::smoother::addsymMatrixConstructorToTable<Foam::DICSmoother>::New(Foam::word const&,
Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double> const&, Foam::FieldField<Foam::Field, double> const&,
Foam::UPtrList<Foam::lduInterfaceField const> const&) at ??:?
• The #include directive (same as in C++):
#6 Foam::lduMatrix::smoother::New(Foam::word const&, Foam::lduMatrix const&, Foam::FieldField<Foam::Field, double>
const&, Foam::FieldField<Foam::Field, double> const&, Foam::UPtrList<Foam::lduInterfaceField const> const&,
Foam::dictionary const&) at ??:?
#7 Foam::GAMGSolver::initVcycle(Foam::PtrList<Foam::Field<double> >&, Foam::PtrList<Foam::Field<double> >&,
Foam::PtrList<Foam::lduMatrix::smoother>&, Foam::Field<double>&, Foam::Field<double>&) const at ??:?
#include “initialConditions”
#8 Foam::GAMGSolver::solve(Foam::Field<double>&, Foam::Field<double> const&, unsigned char) const at ??:?
#9 Foam::fvMatrix<double>::solveSegregated(Foam::dictionary const&) at ??:?
#10 Foam::fvMatrix<double>::solve(Foam::dictionary const&) at ??:?
#11
at ??:?
Do not forget to create the respective include file initialConditions.
#12 __libc_start_main in "/lib64/libc.so.6"
#13
at /home/abuild/rpmbuild/BUILD/glibc-2.17/csu/../sysdeps/x86_64/start.S:126
Floating point exception 146 147
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
• Scalars, vectors, lists and dictionaries. • Scalars, vectors, lists and dictionaries.
• Scalars in OpenFOAM® are represented by a single value, e.g., • List entries are contained within parentheses ( ). A list can contain scalars,
3.14159 vectors, tensors, words, and so on.
• A list of scalars is represented as follows:
name_of_the_list
• Vectors in OpenFOAM® are represented as a list with three components, e.g.,
(
(1.0 0.0 0.0) 0
1
2
• A second order tensor in OpenFOAM® is represented as a list with nine );
components, e.g.,
• A list of vectors is represented as follows:
(
name_of_the_list
1.0 0.0 0.0
(
0.0 1.0 0.0
(0 0 0)
0.0 0.0 1.0
(1 0 0)
)
(2 0 0)
);
148 149
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
• Scalars, vectors, lists and dictionaries. • Scalars, vectors, lists and dictionaries.
• List entries are contained within parentheses ( ). A list can contain scalars, • OpenFOAM® uses dictionaries to specify data in an input file (dictionary file).
vectors, tensors, words, and so on. • A dictionary in OpenFOAM® can contain multiple data entries and at the same
• A list of words is represented as follows time dictionaries can contain sub-dictionaries.
name_of_the_list • To specify a dictionary entry, the name is follow by the keyword entries in curly
( braces:
“word1”
“word2” solvers Dictionary solvers
“word3” {
); p Sub-dictionary p
{
solver PCG;
preconditioner DIC;
tolerance 1e-06;
relTol 0;
}
}
150 151
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
152 153
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
154 155
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
• You can write (the lazy way): • Switches: they are used to enable or disable a function or a feature in the dictionaries.
• Switches are logical values. You can use the following values:
“(left|right|top)Wall”
{
Switches
type fixedValue;
value uniform (0 0 0); false true
}
off on
• You could also try (even lazier): no yes
“.*Wall” n y
{
f t
type fixedValue;
value uniform (0 0 0); none true
}
• You can find all the valid switches in the following file:
• OpenFOAM® understands the syntax of regular expressions (regex or regexp). OpenFOAM-5.x/src/OpenFOAM/primitives/bools/Switch/Switch.C
156 157
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 and post-processing utilities available in OpenFOAM®,
• If you need help about a solver or utility, you can use the option –help. For please read the Doxygen documentation. Just look for the Using OpenFOAM section at the bottom of the
page.
instance:
• If you did not compile the Doxygen documentation, you can access the information online,
http://cpp.openfoam.org/v5/
will print some basic help and usage information about icoFoam
• Remember, you have the source code there so you can always
check the original source.
158 159
9. Flow past a cylinder – From laminar to turbulent flow • This is a three-dimensional and unsteady case.
Workflow of the case At the end of the day, you should get something like this
blockMesh
+
snappyHexMesh
setFields
interFoam functionObjects
Initial conditions – Coarse mesh Solution at Time = 1 second – Coarse mesh
sampling paraview
162 163
3D Dam break – Free surface flow 3D Dam break – Free surface flow
$PTOFC/101OF/3d_damBreak
• To use PyFoam you will need to source it. Type in the terminal:
• We will define the gravity vector in the dictionary g.
• After finding the solution, we will visualize the results. This is an unsteady case so
• $> anaconda2 or $> anaconda3 now we are going to see things moving.
• We are going to briefly address how to post-process multiphase flows.
• Remember, every time you open a new terminal window you need to source OpenFOAM® and PyFoam.
• We are going to generate the mesh using snappyHexMesh, but for the purpose of this
tutorial we are not going to discuss the dictionaries.
• By default, when installing OpenFOAM® and PyFoam you do not need to do this. This is our choice as we
have many things installed and we want to avoid conflicts between applications.
166 167
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
}
168 169
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 }
170 171
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 left domain at time 0. Later, we will initialize the water
32
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 }
172 173
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/p_rgh The file 0/U
174 175
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The file 0/k The file 0/epsilon
176 177
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
30
top
{
($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.
178 179
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
29 writeControl adjustableRunTime;
precise write interval. 68
69
mode component;
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
38
writePrecision 8; eight digits in the output files. 144 };
39 writeCompression uncompressed;
40 • And as the option runTimeModifiable is on, we can modify all
41
42
timeFormat general;
these entries while we are running the simulation.
43 timePrecision 8;
44 • In line 47 we turn on the option adjustTimeStep. This option
45
46
runTimeModifiable yes;
will automatically adjust the time step to achieve the maximum
47 adjustTimeStep yes; desired courant number (lines 49-50). We also set a maximum
48
49 maxCo 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).
180 181
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
84
type volRegion;
functionObjectLibs ("libfieldFunctionObjects.so");
field variable alpha.water in all the domain. 109
110
type probes;
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
88
enabled true;
domain. 113
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
100
(
alpha.water
125
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)
182 183
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
136
yplus
{ which computes the yplus value.
21
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
51
snGradSchemes
{
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
184 solution that is second order accurate. 185
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
19
{
"alpha.water.*"
are using the smoothSolver method. 52
53
{
$p_rgh;
correspond to the last iteration in the loop (we can use a tighter
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;
the computational cost)
22
23
nAlphaSubCycles 1;
cAlpha 1;
keyword nLimiterIter controls the number of MULES iterations 56
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
}
186 187
3D Dam break – Free surface flow 3D Dam break – Free surface flow
The fvSolution dictionary The system directory
82 • In lines 83-89 we setup the entries related to the pressure- • In the system directory you will find the following optional dictionary files:
83
84
PIMPLE
{
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
188 189
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)
Air 17 numberOfSubdomains 4;
alpha.water = 0
18
Water 19 method scotch;
alpha.water = 1
20
boxToCell region
190 191
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:
192 193
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
194 195
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 Only one loop
MULES: Correcting alpha.water
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
198 199
4. Applications/utilities in OpenFOAM®
4. Press apply 5. Directory structure of an OpenFOAM® case
6. Running my first OpenFOAM® case setup blindfold
2. Select alpha.water or the field
you want to use to visualize the
7. A deeper view to my first OpenFOAM® case setup
cells (it has to be a scalar)
8. 3D Dam break – Free surface flow
9. Flow past a cylinder – From laminar to turbulent flow
Cells representing the
3. Select the range you want to water location
visualize. To visualize the
water select Minimum 0.5 and
Maximum 1.
200 201
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
Incompressible and compressible flow
machine, do not forget to load the environment • Depending on the Reynolds number, the flow
can be steady or unsteady.
variables. • This problem has a lot of validation data.
All the dimensions are in meters
202 203
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Workflow of the case Vortex shedding behind a cylinder
blockMesh
Or
fluentMeshToFoam C reeping flow (no s eparation)
S teady flow Re < 5
NOTE: pisoFoam
in the wake
S teady flow
5 < Re < 40 - 46
One single mesh can be used with all
solvers and utilities pimpleFoam
pimpleDyMFoam Laminar vortex s treet
simpleFoam (Von Karman s treet) 40 - 46 < Re < 150 Drag coefficient
functionObjects Uns teady flow
rhoPimpleFoam
interFoam Laminar boundary layer up to 150 < Re < 300
sonicFoam the s eparation point, turbulent Trans ition to turbulence
wake
potentialFoam Uns teady flow 300 < Re < 3 x 10 5
mapFields
Boundary layer trans ition to 5 6
turbulent 3 x 10 < Re < 3 x 10
Uns teady flow
Strouhal number
sampling paraview
204 205
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 Some experimental (E) and numerical (N) results of the flow past a circular
cylinder at various Reynolds numbers cylinder at various Reynolds numbers
[1] Tritton (E) 2.22 – 1.48 – [1] Russel and Wang (N) 1.38 ± 0.007 ± 0.322 1.29 ± 0.022 ± 0.50
[2] Cuntanceau and Bouard (E) – 0.73 – 1.89 [2] Calhoun and Wang (N) 1.35 ± 0.014 ± 0.30 1.17 ± 0.058 ± 0.67
[3] Russel and Wang (N) 2.13 0.94 1.60 2.29 [3] Braza et al. (N) 1.386± 0.015 ± 0.25 1.40 ± 0.05 ± 0.75
[4] Calhoun and Wang (N) 2.19 0.91 1.62 2.18 [4] Choi et al. (N) 1.34 ± 0.011 ± 0.315 1.36 ± 0.048 ± 0.64
[5] Ye et al. (N) 2.03 0.92 1.52 2.27 [5] Liu et al. (N) 1.35 ± 0.012 ± 0.339 1.31 ± 0.049 ± 0.69
[6] Fornbern (N) 2.00 0.92 1.50 2.24 [6] Guerrero (N) 1.38 ± 0.012 ± 0.333 1.408 ± 0.048 ± 0.725
[7] Guerrero (N) 2.20 0.92 1.62 2.21 cl = lift coefficient, cd = drag coefficient, Re = Reynolds number
[1] D. Tritton. Experiments on the flow past a circular cylinder at low Reynolds numbers. Journal of Fluid Mechanics, 6:547-567, 1959. [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] M. Cuntanceau and R. Bouard. Experimental determination of the main features of the viscous flow in the wake of a circular cylinder in uniform translation. Part 1. Steady flow. Journal of Fluid [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.
Mechanics, 79:257-272, 1973. [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,
[3] D. Rusell and Z. Wang. A cartesian grid method for modeling multiple moving objects in 2D incompressible viscous flow. Journal of Computational Physics, 191:177-205, 2003. 1986.
[4] D. Calhoun and Z. Wang. A cartesian grid method for solving the two-dimensional streamfunction-vorticity equations in irregular regions. Journal of Computational Physics. 176:231-275, 2002. [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] T. Ye, R. Mittal, H. Udaykumar, and W. Shyy. An accurate cartesian grid method for viscous incompressible flows with complex immersed boundaries. Journal of Computational Physics, [5] C. Liu, X. Zheng, and C. Sung. Preconditioned multigrid methods for unsteady incompressible flows. Journal of Computational Physics, 139:33-57, 1998.
156:209-240, 1999. [6] J. Guerrero. Numerical Simulation of the unsteady aerodynamics of flapping flight. PhD Thesis, University of Genoa, 2009.
[6] B. Fornberg. A numerical study of steady viscous flow past a circular cylinder. Journal of Fluid Mechanics, 98:819-855, 1980.
[7] J. Guerrero. Numerical simulation of the unsteady aerodynamics of flapping flight. PhD Thesis, University of Genoa, 2009.
206 207
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 At the end of the day, you should get something like this
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case Running the case
• Let us first convert the mesh from a third-party format (Fluent format). • To avoid this problem, type in the terminal,
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c2
1. $> paraFoam -builtin
• In the terminal window type:
• Basically, the problem is related to the names and type of the patches in the file
1. $> foamCleanTutorials
boundary and the boundary conditions (U, p). Notice that OpenFOAM® is telling you
2. $> fluent3DMeshToFoam ../../../meshes_and_geometries/vortex_shedding/ascii.msh what and where is the error.
3. $> checkMesh
Created temporary 'c2.OpenFOAM'
4. $> paraFoam
--> FOAM FATAL IO ERROR:
• In step 2, we convert the mesh from Fluent format to OpenFOAM® format. Have in patch type 'patch' not constraint type 'empty' What
for patch front of field p in file "/home/joegi/my_cases_course/5x/101OF/vortex_shedding/c2/0/p"
Where
• If we try to open the mesh using paraFoam (step 4), it will crash. Can you tell what is From function Foam::emptyFvPatchField<Type>::emptyFvPatchField(const Foam::fvPatch&, const
Foam::DimensionedField<Type, Foam::volMesh>&, const Foam::dictionary&) [with Type = double]
the problem (read the screen)? in file fields/fvPatchFields/constraint/empty/emptyFvPatchField.C at line 80.
FOAM exiting
212 213
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• Remember, when converting meshes the name and type of the patches are not The boundary dictionary file
always set as you would like, so it is always a good idea to take a look at the file
boundary and modify it according to your needs.
18 7
• This dictionary is located in the
• Let us modify the boundary dictionary file. 19 (
20
21
out
{
constant/polyMesh directory.
• In this case, we would like to setup the following primitive type boundary conditions. 22
23
type
nFaces
patch;
80; • This file is automatically created when converting
24 startFace 18180;
25 } or generating the mesh.
26 sym1
27 {
28 type symmetry; • To get a visual reference of the patches, you can
29
30
inGroups
nFaces
1(symmetry);
100; the mesh with paraFoam/paraview.
31 startFace 18260;
32
33
}
sym2
• The type of the out patch is OK.
34 {
35 type symmetry; • The type of the sym1 patch is OK.
36 inGroups 1(symmetry);
37
38
nFaces
startFace
100;
18360; • The type of the sym2 patch is OK.
39 }
40
41
in
{
• The type of the in patch is OK.
42 type patch;
43 nFaces 80;
44 startFace 18460;
45 }
214 215
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The boundary dictionary file • At this point, check that the name and type of the base type boundary conditions
and primitive type boundary conditions are consistent. If everything is ok, we are
ready to go.
46 cylinder
• The type of the cylinder patch is OK.
47
48
{
type wall; • Do not forget to explore the rest of the dictionary files, namely:
49 inGroups 1(wall);
• The type of the back patch is NOT OK.
50
51
nFaces
startFace
80;
18540; Remember, this is a 2D simulation, therefore the • 0/p (p is defined as relative pressure)
52 }
53 back type should be empty. • 0/U
54 {
55 type patch;
56 nFaces 9200; • The type of the front patch is NOT OK. • constant/transportProperties
57
58 }
startFace 18620;
Remember, this is a 2D simulation, therefore the
59
60
front
{
type should be empty. • system/controlDict
61 type patch;
62 nFaces 9200; • Remember, we assign the primitive type • system/fvSchemes
63 startFace 27820;
boundary conditions (numerical values), in the
• system/fvSolution
64 }
65 )
field files found in the directory 0
• Reminder:
• The diameter of the cylinder is 2.0 m.
• And we are targeting for a Re = 200.
216 217
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case Running the case
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c2 • In step 1 we use the utility renumberMesh to make the linear system more diagonal
dominant, this will speed-up the linear solvers. This is inexpensive (even for large
• In the folder c1 you will find the same setup, but to generate the mesh we use
meshes), therefore is highly recommended to always do it.
blockMesh (the mesh is identical).
• In step 2 we run the simulation and save the log file. Notice that we are sending the
• To run this case, in the terminal window type: job to background.
• In step 3 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
1. $> renumberMesh -overwrite job is running in background, we can launch this utility in the same terminal tab.
2. $> icoFoam | tee log.icofoam • In step 4 we use the gnuplot script scripts0/plot_coeffs to plot the force
$> pyFoamPlotWatcher.py log.icofoam coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
3. monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
You will need to launch this script in a different terminal
$> gnuplot scripts0/plot_coeffs • The force coefficients are computed using functionObjects.
4.
You will need to launch this script in a different terminal • After the simulation is over, we use paraFoam to visualize the results. Remember to
5. $> paraFoam use the VCR Controls to animate the solution.
• In the folder c1 you will find the same setup, but to generate the mesh we use
blockMesh (the mesh is identical).
218 219
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
• At this point try to use the following utilities. In the terminal type: Let us run the same case but using a non-uniform field
• $> postProcess –func vorticity –noZero • In the previous case, it took about 150 seconds to onset the instability.
This utility will compute and write the vorticity field. The –noZero option means do not compute the vorticity field for the
solution in the directory 0. If you do not add the –noZero option, it will compute and write the vorticity field for all the • If you are not interested in the initial transient or if you want to speed-up the
saved solutions, including 0
computation, we can add a perturbation in order to trigger the onset of the instability.
• $> postprocess –func 'grad(U)' –latestTime Let us use setFields to initialize a non-uniform flow.
This utility will compute and write the velocity gradient or grad(U) in the whole domain (including at the walls). The
–latestTime option means compute the velocity gradient only for the last saved solution. • This case is already setup in the directory
• $> postprocess –func 'grad(p)'
This utility will compute and write the pressure gradient or grad(U) in the whole domain (including at the walls).
U (0.98480 0.17364 0)
7. $> icoFoam | log.icofoam
U (1 0 0)
$> pyFoamPlotWatcher.py log.icofoam
8.
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
Running the case Does field initialization make a difference?
Let us run the same case but using a non-uniform field • A picture is worth a thousand words. No need to tell you yes, even if the solutions are
• In step 2 we generate the mesh using blockMesh. The name and type of the slightly different.
patches are already set in the dictionary blockMeshDict so there is no need to • This bring us to the next subject, for how long should we run the simulation?
modify the boundary file.
• In step 4 we copy the original files to the directory 0. We do this to keep a backup of
the original files as the file 0/U will be overwritten when using setFields.
• In step 5 we initialize the solution using setFields.
• In step 6 we use the utility renumberMesh to make the linear system more diagonal
dominant, this will speed-up the linear solvers.
• In step 7 we run the simulation and save the log file. Notice that we are sending the
job to background.
• In step 8 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
job is running in background, we can launch this utility in the same terminal tab.
• In step 9 we use the gnuplot script scripts0/plot_coeffs to plot the lift and drag
coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
No field initialization With field initialization
monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
224 225
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
For how long should run the simulation? What about the residuals?
• This is the difficult part when dealing with • Residuals are telling you a lot, but they are
unsteady flows. difficult to interpret.
• Usually you run the simulation until the • In this case the fact that the initial residuals
behavior of a quantity of interest does not are increasing after about 10 seconds, does
oscillates or it becomes periodic. not mean that the solution is diverging. This
• In this case we can say that after the 50 is in indication that something is happening
seconds mark the solution becomes (in this case the onset of the instability).
periodic, therefore there is no need to run up • Remember, the residuals should always
to 350 seconds (unless you want to gather a drop to the tolerance criteria set in the
lot of statistics). fvSolution dictionary (final residuals). If
they do not drop to the desired tolerance, we
• We can stop the simulation at 150 seconds
are talking about unconverged time-steps.
(or maybe less), and do the average of the
quantities between 100 and 150 seconds. • Things that are not clear from the residuals:
• For how long should we run the
simulation?
• Is the solution converging to the right
value?
226 227
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
How to compute force coefficients Can we compute basic statistics of the force coefficients using gnuplot?
• Yes we can. Enter the gnuplot prompt and type:
68 functions • To compute the force coefficients we use
69 {
functionObjects.
195
196
forceCoeffs_object
{
• Remember, functionObjects are defined at the end of
1. gnuplot> stats ‘postProcessing/forceCoeffs_object/0/forceCoeffs.dat’ u 3
205 type forceCoeffs; the controlDict dictionary file.
206 functionObjectLibs ("libforces.so"); This will compute the basic statistics of all the rows in the file forceCoeffs.dat (we are sampling column 3 in the input file)
208 patches (cylinder); • In line 195 we give a name to the functionObject.
209
2. gnuplot> stats ‘postProcessing/forceCoeffs_object/0/forceCoeffs.dat’ every ::3000::7000 u 3
210 pName p; • In line 208 we define the patch where we want to
211 Uname U; 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)
212 rhoName rhoInf; compute the forces.
213 rhoInf 1.0;
214 • In lines 212-213 we define the reference density value. 3. gnuplot> plot ‘postProcessing/forceCoeffs_object/0/forceCoeffs.dat’ u 3 w l
215 //// Dump to file This will plot column 3 against the row number (iteration number)
216 log true; • In line 218 we define the center of rotation (for moments).
217
218 CofR (0.0 0 0); • In line 219 we define the lift force axis. 4. gnuplot> exit
219 liftDir (0 1 0); To exit gnuplot
220 dragDir (1 0 0); • In line 220 we define the drag force axis.
221 pitchAxis (0 0 1);
222 magUInf 1.0; • In line 221 we define the axis of rotation for moment
223
224
lRef 1.0;
Aref 2.0;
computation.
225
• In line 223 we give the reference length (for computing
• Remember the force coefficients information is saved in the file forceCoeffs.dat
226 outputControl timeStep;
227 outputInterval 1; the moments)
228 }
• In line 224 we give the reference area (in this case the located in the directory postProcessing/forceCoeffs_object/0
255 };
frontal area).
• The output of this functionObject is saved in the file
forceCoeffs.dat located in the directory
forceCoeffs_object/0/
228 229
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
On the solution accuracy On the solution tolerance and linear solvers
17 ddtSchemes
• At the end of the day we want a solution that is second order 17 solvers
• We define the solution tolerance and linear solvers in the
18 { accurate. 18 { dictionary fvSolution.
20 default backward; 31 p
22
23
}
• We define the discretization schemes (and therefore the 32
33
{
solver GAMG;
• To solve the pressure (p) we are using the GAMG method
24 gradSchemes accuracy) in the dictionary fvSchemes. 34 tolerance 1e-6; with an absolute tolerance of 1e-6 and a relative tolerance
25 { 35 relTol 0;
relTol of 0.01.
31
37 }
default cellLimited leastSquares 1;
• In this case, for time discretization (ddtSchemes) we are 36
37
smoother
nPreSweeps
GaussSeidel;
0;
38 using the backward method. 38 nPostSweeps 2; • The entry pFinal refers to the final correction of the PISO
39 divSchemes 39 cacheAgglomeration on;
loop. It is possible to use a tighter convergence criteria only
40 {
• For gradient discretization (gradSchemes) we are using the 40 agglomerator faceAreaPair;
41 default none; 41 nCellsInCoarsestLevel 100; in the last iteration.
45 div(phi,U) Gauss linearUpwindV default; leastSquares method with slope limiters (cellLimited). 42 mergeLevels 1;
49 } 43 }
• To solve U we are using the solver PBiCG and the DILU
50
• For the discretization of the convective terms (divSchemes) 44
51 laplacianSchemes 45 pFinal
preconditioner, with an absolute tolerance of 1e-8 and a
52 { we are using linearUpwindV interpolation method for the 46 {
59 default Gauss linear limited 1; 47 $p; relative tolerance relTol of 0 (the solver will stop iterating
60 } term div(rho,U). 48 relTol 0;
61 49 } when it meets any of the conditions).
62 interpolationSchemes • For the discretization of the Laplacian (laplacianSchemes 50
63 { 51 U • Solving for the velocity is relative inexpensive, whereas
64 default linear; and snGradSchemes) we are using the Gauss linear 52 {
solving for the pressure is expensive.
66
67
}
limited 1 method 53
54
solver
preconditioner
PBiCG;
DILU;
68 snGradSchemes 55 tolerance 1e-08; • The PISO sub-dictionary contains entries related to the
69 { • This method is second order accurate. 56 relTol 0;
71 default limited 1; 57 } pressure-velocity coupling (in this case the PISO method).
72 } 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 }
230 231
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
On the runtime parameters The output screen
• This is the output screen of the icoFoam solver.
nCorrector 1
17 application icoFoam;
• This case starts from the latest saved solution (startFrom).
18
20 startFrom latestTime; • In this case as there are no saved solutions, it will start from Time = 350
Courant number
21
22 startTime 0;
0 (startTime). Courant Number mean: 0.11299953 max: 0.87674198
23 DILUPBiCG: Solving for Ux, Initial residual = 0.0037946307, Final residual = 4.8324843e-09, No Iterations 3
24 stopAt endTime; • It will run up to 350 seconds (endTime). DILUPBiCG: Solving for Uy, Initial residual = 0.011990022, Final residual = 5.8815028e-09, No Iterations 3
GAMG: Solving for p, Initial residual = 0.022175872, Final residual = 6.2680545e-07, No Iterations 14
26
GAMG: Solving for p, Initial residual = 0.0033723932, Final residual = 5.8494331e-07, No Iterations 8
27 endTime 350; • The time step of the simulation is 0.05 seconds (deltaT). The nNonOrthogonalCorrectors 2
GAMG: Solving for p, Initial residual = 0.0010074964, Final residual = 4.4726195e-07, No Iterations 7
29
33 deltaT 0.05; time step has been chosen in such a way that the Courant time step continuity errors : sum local = 1.9569266e-11, global = -3.471923e-14, cumulative = -2.8708402e-10
GAMG: Solving for p, Initial residual = 0.0023505548, Final residual = 9.9222424e-07, No Iterations 8
34
35 writeControl runTime;
number is less than 1 GAMG: Solving for p, Initial residual = 0.00045248026, Final residual = 7.7250386e-07, No Iterations 6
GAMG: Solving for p, Initial residual = 0.00014664077, Final residual = 4.5825218e-07, No Iterations 5 pFinal
43 time step continuity errors : sum local = 2.0062733e-11, global = 1.2592813e-13, cumulative = -2.8695809e-10
44 writeInterval 1; • It will write the solution every 1 second (writeInterval) of ExecutionTime = 746.46 s ClockTime = 807 s
45
52 purgeWrite 0;
simulation time (runTime). faceSource inMassFlow output:
53 sum(in) of phi = -40 Mass flow at in patch
• It will keep all the solution directories (purgeWrite).
nCorrector 2
54 writeFormat ascii;
55 faceSource outMassFlow output:
sum(out) of phi = 40 Mass flow at out patch
56
57
writePrecision 8;
• It will save the solution in ascii format (writeFormat).
fieldAverage fieldAverage output:
58 writeCompression off;
59 • The write precision is 8 digits (writePrecision). Calculating averages Computing averages of fields
60 timeFormat general; Writing average fields nCorrectors 2
61 • And as the option runTimeModifiable is on, we can modify
62 timePrecision 6; forceCoeffs forceCoeffs_object output:
63 all these entries while we are running the simulation. Cm = 0.0043956828
64 runTimeModifiable true; Cd = 1.4391786
Cl = 0.44532594 Force
Cl(f) = 0.22705865 coefficients
Cl(r) = 0.21826729
232 233
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 this time using a potential solver Running the case
• In this case we are going to use the potential solver potentialFoam (remember potential Let us run the same case but this time using a potential solver
solvers are inviscid, irrotational and incompressible)
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c4
• This solver is super fast and it can be used to find a solution to be used as initial conditions
(non-uniform field) for an incompressible solver. • Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this
case we will use blockMesh.
• A good initial condition will accelerate and improve the convergence rate.
• This case is already setup in the directory
• To run this case, in the terminal window type:
234 235
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case Potential solution
Let us run the same case but this time using a potential solver • Using a potential solution as initial conditions is much better than using a uniform
• In step 2 we generate the mesh using blockMesh. The name and type of the flow. It will speed up the solution and it will give you more stability.
patches are already set in the dictionary blockMeshDict so there is no need to • Finding a solution using the potential solver is inexpensive.
modify the boundary file.
• In step 4 we copy the original files to the directory 0. We do this to keep a backup of
the original files as they will be overwritten by the solver potentialFoam.
• In step 5 we run the solver. We use the option –noFunctionObjects to avoid
conflicts with the functionobjects. The options –writep and –writePhi will write
the pressure field and fluxes respectively.
• At this point, if you want to use this solution as initial conditions for an incompressible
solver, just copy the files U and p into the start directory of the incompressible case
you are looking to run. Have in mind that the meshes need to be the same.
• Be careful with the name and type of the boundary conditions, they should be same
between the potential case and incompressible case.
Velocity field Pressure field
236 237
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The output screen Let us map a solution from a coarse mesh to a finer mesh
• This is the output screen of the potentialFoam solver. • It is also possible to map the solution from a coarse mesh to a finer mesh (and all the
• The output of this solver is also a good indication of the sensitivity of the mesh quality way around).
to gradients computation. If you see that the number of iterations are dropping • For instance, you can compute a full Navier Stokes solution in a coarse mesh (fast
iteration after iteration, it means that the mesh is fine. solution), and then map it to a finer mesh.
• If the number of iterations remain stalled, it means that the mesh is sensitive to • Let us map the solution from the potential solver to a finer mesh (if you want you can
gradients, so should use non-orthogonal correction. map the solution obtained using icoFoam). To do this we will use the utility
• In this case we have a good mesh. mapFields.
• This case is already setup in the directory
Calculating potential flow Velocity computation
DICPCG: Solving for Phi, Initial residual = 2.6622265e-05, Final residual = 8.4894837e-07, No Iterations 27 Initial approximation
DICPCG: Solving for Phi, Initial residual = 1.016986e-05, Final residual = 9.5168103e-07, No Iterations 9
DICPCG: Solving for Phi, Initial residual = 4.0789046e-06, Final residual = 7.7788216e-07, No Iterations 5
DICPCG: Solving for Phi, Initial residual
DICPCG: Solving for Phi, Initial residual
=
=
1.8251249e-06, Final residual = 8.8483568e-07, No Iterations 1
1.1220074e-06, Final residual = 5.6696809e-07, No Iterations 1
$PTOFC/101OF/vortex_shedding/c6
DICPCG: Solving for Phi, Initial residual = 7.1187246e-07, Final residual = 7.1187246e-07, No Iterations 0
Continuity error = 1.3827583e-06
Interpolated velocity error = 7.620206e-07
nNonOrthogonalCorrectors 5
Calculating approximate pressure field Pressure computation
DICPCG: Solving for p, Initial residual = 0.0036907012, Final residual = 9.7025397e-07, No Iterations 89
DICPCG: Solving for p, Initial residual = 0.0007470416, Final residual = 9.9942495e-07, No Iterations 85
DICPCG: Solving for p, Initial residual = 0.00022829496, Final residual = 8.6107759e-07, No Iterations 36
DICPCG: Solving for p, Initial residual = 7.9622793e-05, Final residual = 8.4360883e-07, No Iterations 31
DICPCG: Solving for p, Initial residual = 2.8883108e-05, Final residual = 8.7152873e-07, No Iterations 25
DICPCG: Solving for p, Initial residual = 1.151539e-05, Final residual = 9.7057871e-07, No Iterations 9
ExecutionTime = 0.17 s ClockTime = 0 s
End
238 239
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case Running the case
Let us map a solution from a coarse mesh to a finer mesh Let us map a solution from a coarse mesh to a finer mesh
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c6 • In step 2 we generate a finer mesh using blockMesh. The name and type of the
• To generate the mesh, use blockMesh (remember this mesh is finer). patches are already set in the dictionary blockMeshDict so there is no need to
modify the boundary file.
• To run this case, in the terminal window type:
• In step 4 we copy the original files to the directory 0. We do this to keep a backup of
the original files as they will be overwritten by the utility mapFields.
1. $> foamCleanTutorials
• In step 5 we use the utility mapFields with the following options:
2. $> blockMesh
• We copy the solution from the directory ../c4
3. $> rm –rf 0
• The options –consistent is used when the domains and BCs are the same.
4. $> cp –r 0_org 0
• The option –noFunctionObjects is used to avoid conflicts with the
5. $> mapfields ../c4 –consistent –noFunctionObjects –mapMethod cellPointInterpolate -sourceTime 0 functionObjects.
6. $> paraFoam • The option –mapMethod cellPointInterpolate defines the interpolation
method.
• The option -sourceTime 0 defines the time from which we want to interpolate
the solution.
240 241
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The meshes and the mapped fields The output screen
• This is the output screen of the mapFields utility.
Coarse mesh Fine mesh
• The utility mapFields, will try to interpolate all fields in the source directory.
• You can control the target time via the startFrom and startTime keywords in the
controlDict dictionary file.
Source mesh size: 9200 Target mesh size: 36800 Source and target mesh cell count
interpolating Phi
interpolating p Interpolated fields
interpolating U
End
242 243
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Setting a turbulent case • The following dictionaries remain unchanged
• So far we have used laminar incompressible solvers. • system/blockMeshDict
• Let us do a turbulent simulation. • constant/polyMesh/boundary
• When doing turbulent simulations, we need to choose the turbulence model, define • 0/p
the boundary and initial conditions for the turbulent quantities, and modify the
fvSchemes and fvSolution dictionaries to take account for the new variables we • 0/U
are solving (the transported turbulent quantities).
• This case is already setup in the directory • The following dictionaries need to be adapted for the turbulence case
• constant/transportProperties
$PTOFC/101OF/vortex_shedding/c14
• system/controlDict
• system/fvSchemes
• system/fvSolution
• In this file we set the transport model and the kinematic viscosity (nu). • In this dictionary file we select what model we would like to use (laminar or turbulent).
• In this case we are interested in modeling turbulence, therefore the dictionary is as follows
• If you want to know the models available use the banana method.
246 247
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The controlDict dictionary The fvSchemes dictionary
17 application pimpleFoam;
• This case will start from the last saved solution (startFrom). If there is • In this case, for time discretization (ddtSchemes) we are using the
18 no solution, the case will start from time 0 (startTime). 17 ddtSchemes blended CrankNicolson method. The blending coefficient goes from 0
18 {
20 startFrom latestTime;
21 default CrankNicolson 0.5; to 1, where 0 is equivalent to the Euler method and 1 is a pure Crank
21 • It will run up to 500 seconds (endTime).
22 startTime 0; 22 } Nicolson.
24 gradSchemes
23 • The initial time step of the simulation is 0.001 seconds (deltaT).
24 stopAt endTime; 25 { • For gradient discretization (gradSchemes) we are using as default
31 default cellLimited leastSquares 1;
25
• It will write the solution every 1 second (writeInterval) of simulation time 36 grad(U) cellLimited Gauss linear 1; option the leastSquares method. For grad(U) we are using Gauss
26 endTime 500;
27 (runTime). 37 } linear with slope limiters (cellLimited). You can define different
39 divSchemes
28 deltaT 0.001;
40 {
methods for every term in the governing equations, for example, you
32 • It will keep all the solution directories (purgeWrite). 41 default none; can define a different method for grad(p).
33 writeControl runTime;
47 div(phi,U) Gauss linearUpwindV grad(U);
41 • It will save the solution in ascii format (writeFormat). 49 div((nuEff*dev2(T(grad(U))))) Gauss linear; • For the discretization of the convective terms (divSchemes) we are
42 writeInterval 1;
51 div(phi,k) Gauss linearUpwind default;
43
• The write precision is 8 digits (writePrecision). 52 div(phi,omega) Gauss linearUpwind default;
using linearUpwindV interpolation method with slope limiters for the
50 purgeWrite 0;
51 63 } term div(phi,U).
52 writeFormat ascii; • And as the option runTimeModifiable is on, we can modify all these 65 laplacianSchemes
53 entries while we are running the simulation. 66 { • For the terms div(phi,k) and div(phi,omega) we are using
74 default Gauss linear limited 1;
54 writePrecision 8;
75 }
linearUpwind interpolation method with no slope limiters. These terms
55 • In line 64 we turn on the option adjustTimeStep. This option will 77 interpolationSchemes are related to the turbulence modeling.
56 writeCompression off;
57 automatically adjust the time step to achieve the maximum desired 78 {
58 timeFormat general; courant number maxCo (line 66). 79 default linear; • For the term div((nuEff*dev2(T(grad(U))))) we are using linear
81 }
59
83 snGradSchemes
interpolation (this term is related to turbulence modeling).
60 timePrecision 6; • We also set a maximum time step maxDeltaT in line 67. 84 {
61
86 default limited 1; • For the discretization of the Laplacian (laplacianSchemes and
62 runTimeModifiable yes; • Remember, the first time step of the simulation is done using the value 87 } snGradSchemes) we are using the Gauss linear limited 1 method.
63
64 adjustTimeStep yes; set in line 28 and then it is automatically scaled to achieve the desired 89 wallDist
65 maximum values (lines 66-67). 90 { • To compute the distance to the wall and normals to the wall, we use the
91 method meshWave;
66 maxCo 0.9;
92 } method meshWave. This only applies when using wall functions
67 maxDeltaT 0.1; • The feature adjustTimeStep is only present in the PIMPLE family (turbulence modeling).
solvers, but it can be added to any solver by modifying the source code.
• This method is second order accurate.
248 249
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 the pressure (p) we are using the GAMG method, with an 17 solvers
• To solve UFinal we are using the solver PBiCGStab with an absolute
18 { absolute tolerance of 1e-6 and a relative tolerance relTol of 0.001. 18 { tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
31 p Notice that we are fixing the number of minimum iterations (minIter). 77 UFinal fixing the number of minimum iterations (minIter).
32 { 78 {
33 solver GAMG; 79 solver PBiCGStab;
34 tolerance 1e-6;
• To solve the final pressure correction (pFinal) we are using the PCG 80 preconditioner DILU;
• To solve omega and omegaFinal we are using the solver PBiCGStab
35 relTol 0.001; method with the DIC preconditioner, with an absolute tolerance of 1e-6 81 tolerance 1e-08; with an absolute tolerance of 1e-8 and a relative tolerance relTol of 0.
36 smoother GaussSeidel; and a relative tolerance relTol of 0. 82 relTol 0; Notice that we are fixing the number of minimum iterations (minIter).
37 nPreSweeps 0; 83 minIter 3;
38 nPostSweeps 2; 84 }
39 cacheAgglomeration on;
• Notice that we can use different methods between p and pFinal. In this 85
• To solve k we are using the solver PBiCGStab with an absolute
40 agglomerator faceAreaPair; case we are using a tighter tolerance for the last iteration. 86 omega tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
41 nCellsInCoarsestLevel 100; 87 { fixing the number of minimum iterations (minIter).
42 mergeLevels 1; • We are also fixing the number of minimum iterations (minIter). This 88 solver PBiCGStab;
44 minIter 2; 89 preconditioner DILU;
45 }
entry is optional. 90 tolerance 1e-08;
46 91 relTol 0;
47 pFinal • To solve U we are using the solver PBiCGStab with the DILU 92 minIter 3;
48 { preconditioner, an absolute tolerance of 1e-8 and a relative tolerance 93 }
49 solver PCG; 94
50 preconditioner DIC;
relTol of 0. Notice that we are fixing the number of minimum iterations 95 omegaFinal
51 tolerance 1e-06; (minIter). 96 {
52 relTol 0; 97 solver PBiCGStab;
54 minIter 3; 98 preconditioner DILU;
55 } 99 tolerance 1e-08;
56 100 relTol 0;
57 U 101 minIter 3;
58 { 102 }
59 solver PBiCGStab; 103
60 preconditioner DILU; 104 k
61 tolerance 1e-08; 105 {
62 relTol 0; 106 solver PBiCGStab;
63 minIter 3; 107 preconditioner DILU;
64 } 108 tolerance 1e-08;
109 relTol 0;
110 minIter 3;
111 }
250 251
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The fvSolution dictionary • The following dictionaries are new
• 0/k
113 kFinal
• To solve kFinal we are using the solver PBiCGStab with an absolute
114
115
{
solver PBiCGStab;
tolerance of 1e-8 and a relative tolerance relTol of 0. Notice that we are
fixing the number of minimum iterations (minIter).
• 0/omega
116 preconditioner DILU;
117
118
tolerance
relTol
1e-08;
0;
• In lines 123-133 we setup the entries related to the pressure-velocity • 0/nut
119 minIter 3; coupling method used (PIMPLE in this case). Setting the keyword
120 } nOuterCorrectors to 1 is equivalent to running using the PISO method.
121
122
} These are the field variables related to the closure equations of the turbulent
• To gain more stability we are using 1 outer correctors
123
124
PIMPLE
{ (nOuterCorrectors), 3 inner correctors or PISO correctors model.
126 nOuterCorrectors 1; (nCorrectors), and 1 correction due to non-orthogonality
127 //nOuterCorrectors 2;
128 (nNonOrthogonalCorrectors).
129 nCorrectors 3;
130 nNonOrthogonalCorrectors 1; • Remember, adding corrections increase the computational cost.
133
134
}
• In lines 135-147 we setup the under relaxation factors used during the
• As we are going to use the model we need to define the initial
135
136
relaxationFactors
{
outer corrections (pseudo transient iterations). If you are working in conditions and boundaries conditions.
137 fields PISO mode (only one outer correction or nOuterCorrectors), these
138 { values are ignored.
139
140 }
p 0.3; • To define the IC/BC we will use the free stream values of and
141 equations
142
143
{
U 0.7; • In the following site, you can find a lot information abut choosing initial and
144 k 0.7;
145
146 }
omega 0.7; boundary conditions for the different turbulence models:
147 }
• https://turbmodels.larc.nasa.gov/
252 253
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Turbulence model free-stream boundary conditions The file 0/k
19 internalField uniform 0.00015;
• The initial value for the turbulent kinetic energy can be found as follows 20 • We are using uniform initial conditions (line 19).
21 boundaryField
22 { • For the in patch we are using a fixedValue boundary
23 out
24 { condition.
25 type inletOutlet;
26 inletValue uniform 0.00015; • For the out patch we are using an inletOutlet boundary
27 value uniform 0.00015;
• The initial value for the specific kinetic energy can be found as follows 28 } condition (this boundary condition avoids backflow).
29 sym1
30
31
{
type symmetryPlane;
• For the cylinder patch (which is base type wall), we
32 } are using the kqRWallFunction boundary condition.
33 sym2
34 { This is a wall function, we are going to talk about this
35 type symmetryPlane; when we deal with turbulence modeling. Remember,
36 }
• Where is the viscosity ratio and is the turbulence intensity. 37 in we can use wall functions only if the patch is of base
38
39
{
type fixedValue;
type wall.
40 value uniform 0.00015;
• If you are working with external aerodynamics or virtual wind tunnels, you can use the following 41 } • The rest of the patches are constrained.
42 cylinder
reference values for the turbulence intensity and the viscosity ratio. They work most of the 43
44
{
type kqRWallFunction;
• FYI, the inlet velocity is 1 and the turbulence intensity is
times, but it is a good idea to have some experimental data or a better initial estimate. 45 value uniform 0.00015; equal to 1%.
46 }
47 back
48 {
Low Medium High 49 type empty;
50 }
51 front
1.0 % 5.0 % 10.0 % 52 {
53 type empty;
54 }
1 10 100 55 }
254 255
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The file 0/omega The file 0/nut
19 internalField uniform 0.075;
20 19 internalField uniform 0;
21 boundaryField • We are using uniform initial conditions (line 19). 20 • We are using uniform initial conditions (line 19).
22 { 21 boundaryField
23 out • For the in patch we are using a fixedValue boundary 22 { • For the in patch we are using the calculated boundary
24 { 23 out
25 type inletOutlet; condition. 24 { condition (nut is computed from kappa and omega)
26 inletValue uniform 0.075; 25 type calculated;
27
28 }
value uniform 0.075; • For the out patch we are using an inletOutlet boundary 26
27 }
value uniform 0; • For the out patch we are using the calculated
29 sym1 condition (this boundary condition avoids backflow). 28 sym1 boundary condition (nut is computed from kappa and
30 { 29 {
omega)
31
32 }
type symmetryPlane;
• For the cylinder patch (which is base type wall), we 30
31 }
type symmetryPlane;
33 sym2 are using the omegaWallFunction boundary condition. 32 sym2 • For the cylinder patch (which is base type wall), we
34 { 33 {
35 type symmetryPlane; This is a wall function, we are going to talk about this 34 type symmetryPlane; are using the nutkWallFunction boundary condition.
36 } when we deal with turbulence modeling. Remember, we 35
36
}
in
This is a wall function, we are going to talk about this
37 in
38 { can use wall functions only if the patch is of base type 37 { when we deal with turbulence modeling. Remember, we
39 type fixedValue; 38 type calculated;
40 value uniform 0.075;
wall. 39 value uniform 0;
can use wall functions only if the patch is of base type
41 } 40 } wall.
42 cylinder • The rest of the patches are constrained. 41 cylinder
43 { 42 {
• The rest of the patches are constrained.
44
45
type
Cmu
omegaWallFunction;
0.09;
• FYI, the inlet velocity is 1 and the eddy viscosity ratio is 43
44
type
Cmu
nutkWallFunction;
0.09;
46 kappa 0.41; equal to 10. 45 kappa 0.41; • Remember, the turbulent viscosity (nut) is equal to
47 E 9.8; 46 E 9.8;
48 beta1 0.075; 47 value uniform 0;
49 value uniform 0.075; 48 }
50 } 49 back
51 back 50 {
52 { 51 type empty;
53 type empty; 52 }
54 } 53 front
55 front 54 {
56 { 55 type empty;
57 type empty; 56 }
58 } 57 }
59 }
256 257
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case – Setting a turbulent case Running the case
Setting a turbulent case
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c14
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this case we will use • In step 3 we use the utility renumberMesh to make the linear system more diagonal
blockMesh. dominant, this will speed-up the linear solvers.
• To run this case, in the terminal window type:
• In step 4 we run the simulation and save the log file. Notice that we are sending the
job to background.
1. $> foamCleanTutorials
• In step 5 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
2. $> blockMesh job is running in background, we can launch this utility in the same terminal tab.
3. $> renumberMesh -overwrite • In step 6 we use the gnuplot script scripts0/plot_coeffs to plot the force
$> pimpleFoam | log coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
4. monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
You will need to launch this script in a different terminal
$> pyFoamPlotWatcher.py log • In step 7 we use the utility postProcess to compute the value of each saved
5. solution (we are going to talk about when we deal with turbulence modeling).
You will need to launch this script in a different terminal
8. $> paraFoam
258 259
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
pimpleFoam output screen
The output screen
Courant Number mean: 0.088931706 max: 0.90251464 Courant number
deltaT = 0.040145538
Time = 499.97
Time step
Simulation time
• This is the output screen of the yPlus utility.
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
Time = 500.01
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 Reading field U
time step continuity errors : sum local = 3.2664019e-10, global = -1.3568363e-12, cumulative = -9.8446438e-08
GAMG: Solving for p, Initial residual = 0.16889316, Final residual = 0.00014947209, No Iterations 7 Reading/calculating face flux field phi
GAMG: Solving for p, Initial residual = 0.0051876466, Final residual = 3.7123156e-06, No Iterations 8
time step continuity errors : sum local = 2.2950163e-10, global = -8.0710768e-13, cumulative = -9.8447245e-08 Transport model
PIMPLE: iteration 2 Outer iteration 2 (nOuterCorrectors) Selecting incompressible transport model Newtonian
DILUPBiCG: Solving for Ux, Initial residual = 0.0013482181, Final residual = 4.1395468e-10, No Iterations 3 Selecting RAS turbulence model kOmegaSST Turbulence model
DILUPBiCG: Solving for Uy, Initial residual = 0.0032433196, Final residual = 3.3969121e-09, No Iterations 3 kOmegaSSTCoeffs Model coefficients
GAMG: Solving for p, Initial residual = 0.10067317, Final residual = 8.9325549e-05, No Iterations 7
{
GAMG: Solving for p, Initial residual = 0.0042844521, Final residual = 3.0190597e-06, No Iterations 8
time step continuity errors : sum local = 1.735023e-10, global = -2.0653335e-13, cumulative = -9.8447452e-08 alphaK1 0.85;
GAMG: Solving for p, Initial residual = 0.0050231165, Final residual = 3.2656397e-06, No Iterations 8 alphaK2 1;
DICPCG: Solving for p, Initial residual = 0.00031459519, Final residual = 9.4260163e-07, No Iterations 36 pFinal alphaOmega1 0.5;
time step continuity errors : sum local = 5.4344408e-11, global = 4.0060595e-12, cumulative = -9.8443445e-08
alphaOmega2 0.856;
DILUPBiCG: Solving for omega, Initial residual = 0.00060510266, Final residual = 1.5946601e-10, No Iterations 3
DILUPBiCG: Solving for k, Initial residual = 0.0032163247, Final residual = 6.9350899e-10, No Iterations 3 gamma1 0.55555556; Patch where we are computing y+
bounding k, min: -3.6865398e-05 max: 0.055400108 average: 0.0015914926 gamma2 0.44;
ExecutionTime = 1689.51 s ClockTime = 1704 s beta1 0.075;
beta2 0.0828;
fieldAverage fieldAverage output:
Calculating averages Message letting you know that kappa and omega residuals betaStar 0.09;
the variable is becoming a1 0.31;
forceCoeffs forceCoeffs_object output: b1 1;
Cm = 0.0023218797 unbounded
c1 10;
Cd = 1.1832452 Minimum, maximum and average values
Cl = -1.3927646 Force coefficients F3 false;
Cl(f) = -0.69406044 }
Cl(r) = -0.6987042
Patch 4 named cylinder y+ : min: 0.94230389 max: 12.696632 average: 7.3497345
fieldMinMax minmaxdomain output:
min(p) = -1.5466372 at location (-0.040619337 -1.033408 0)
max(p) = 0.54524589 at location (-1.033408 0.040619337 1.4015759e-17) Writing yPlus to field yPlus Writing the field to the solution directory
min(U) = (0.94205232 -1.0407426 -5.0319219e-19) at location (-0.70200781 -0.75945224 -1.3630525e-17)
max(U) = (1.8458167 0.0047368607 4.473279e-19) at location (-0.12989625 -1.0971865 2.4694467e-17) Minimum and
min(k) = 1e-15 at location (1.0972618 1.3921931 -2.2329889e-17) maximum values
max(k) = 0.055400108 at location (2.1464795 0.42727634 0)
min(omega) = 0.2355751 at location (29.403674 19.3304 0)
max(omega) = 21.477072 at location (1.033408 0.040619337 1.3245285e-17) 260 261
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Using a compressible solver • The following dictionaries remain unchanged
• So far we have only used incompressible solvers.
• Let us use the compressible solver rhoPimpleFoam, which is a • system/blockMeshDict
Transient solver for laminar or turbulent flow of compressible fluids for HVAC and
• constant/polyMesh/boundary
similar applications. Uses the flexible PIMPLE (PISO-SIMPLE) solution for time-
resolved and pseudo-transient simulations.
• When working with compressible solver we need to define the thermodynamical • Reminder:
properties of the working fluid and the temperature field (we are also solving the • The diameter of the cylinder is 0.002 m.
energy equation)
• The working fluid is air at 20° Celsius and at a sea level.
• This case is already setup in the directory
• Isothermal flow.
$PTOFC/101OF/vortex_shedding/c24 • And we are targeting for a Re = 200.
262 263
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The constant directory The thermophysicalProperties dictionary file
• In this directory, we will find the following compulsory dictionary files: • This dictionary file is located in the directory constant.
18 thermoType Thermophysical models are concerned with energy, heat
19 {
20 type hePsiThermo; and physical properties.
21 mixture pureMixture;
• thermophysicalProperties 22
23
transport
thermo
const;
hConst;
• In the sub-dictionary thermoType (lines 18-27), we
24 equationOfState perfectGas; define the thermophysical models.
• turbulenceProperties 25
26
specie
energy
specie;
sensibleEnthalpy; • The transport modeling concerns evaluating dynamic
27 }
28 viscosity (line 22). In this case the viscosity is constant.
29 mixture
30
31
{
specie
• The thermodynamic models (thermo) are concerned with
• thermophysicalProperties contains the definition of the physical 32
33
{
nMoles 1;
evaluating the specific heat Cp (line 23). In this case Cp
is constant
properties of the working fluid. 34
35 }
molWeight 28.9;
264 265
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The thermophysicalProperties dictionary file The turbulenceProperties dictionary file
• In this dictionary file we select what model we would like to use (laminar or
• In the sub-dictionary mixture (lines 29-46), we define the
18 thermoType thermophysical properties of the working fluid.
turbulent).
19 {
20
21
type
mixture
hePsiThermo;
pureMixture;
• In this case, we are defining the properties for air at 20° • This dictionary is compulsory.
22 transport const; Celsius and at a sea level.
23 thermo hConst;
24
25
equationOfState
specie
perfectGas;
specie;
• As we do not want to model turbulence, the dictionary is defined as follows,
26 energy sensibleEnthalpy;
27 }
28
29 mixture
30 {
31 specie
32 {
33 nMoles 1;
34 molWeight 28.9;
35 } 17 simulationType laminar;
36 thermodynamics
37 {
38 Cp 1005;
39 Hf 0;
40 }
41 transport
42 {
43 mu 1.84e-05;
44 Pr 0.713;
45 }
46 }
266 267
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The 0 directory The file 0/p
• This file contains the boundary and initial conditions
• In this directory, we will find the dictionary files that contain the boundary and 17
18
dimensions [1 -1 -2 0 0 0 0];
for the scalar field pressure (p). We are working
with absolute pressure.
initial conditions for all the primitive variables. 19
20
internalField uniform 101325;
21 boundaryField
• Contrary to incompressible flows where we defined
• As we are solving the compressible laminar Navier-Stokes equations, we will 22
23
{
in relative pressure, this is the absolute pressure.
24 {
find the following field files: 25
26 }
type zeroGradient;
• Also, pay attention to the units (line 17). The
28 out pressure is defined in Pascal.
29 {
30
31
type
value
fixedValue;
uniform 101325;
• We are using uniform initial conditions (line 19).
• p (pressure) 32
34
}
cylinder • For the in patch we are using a zeroGradient
35 {
boundary condition.
• T (temperature) 36
37 }
type zeroGradient;
268 269
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The file 0/T The file 0/U
17 dimensions [0 1 -1 0 0 0 0];
17 dimensions [0 0 0 -1 0 0 0];
• This file contains the boundary and initial conditions 18 • This file contains the boundary and initial conditions
18 for the scalar field temperature (T). 19
20
internalField uniform (1.5 0 0);
for the dimensional vector field U.
19 internalField uniform 293.15;
20 21 boundaryField
21 boundaryField • Also, pay attention to the units (line 17). The 22 { • We are using uniform initial conditions and the
22 { temperature is defined in Kelvin. 23
24
in
{
numerical value is (1.5 0 0) (keyword internalField in
23 in
24 { 25 type fixedValue; line 19).
25 type fixedValue; • We are using uniform initial conditions (line 19). 26 value uniform (1.5 0 0);
26 value $internalField; 27 }
• For the in patch we are using a fixedValue boundary
27 } • For the in patch we are using a fixedValue boundary 29 out
29 out 30 { condition.
30 { condition. 31 type inletOutlet;
31 type inletOutlet; 32 phi phi;
• For the out patch we are using a inletOutlet
32 value $internalField; • For the out patch we are using a inletOutlet 33 inletValue uniform (0 0 0);
33 inletValue $internalField; 34 value uniform (0 0 0); boundary condition (in case of backflow).
34 } boundary condition (in case of backflow). 35 }
37 cylinder
36 cylinder
• For the cylinder patch we are using a zeroGradient
37 { • For the cylinder patch we are using a zeroGradient 38 {
38 type zeroGradient; 39 type fixedValue; boundary condition.
39 } boundary condition. 40 value uniform (0 0 0);
41 }
41 sym1
• The rest of the patches are constrained.
42 { • The rest of the patches are constrained. 43
44
sym1
{
43 type symmetryPlane;
44 } 45 type symmetryPlane;
46 sym2 46 }
47 { 48 sym2
48 type symmetryPlane; 49 {
49 } 50 type symmetryPlane;
51 back 51 }
52 { 53 back
53 type empty; 54 {
54 } 55 type empty;
56 front 56 }
57 { 58 front
58 type empty; 59 {
59 } 60 type empty;
60 } 61 }
62 }
270 271
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The system directory The controlDict dictionary
272 273
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
The controlDict dictionary The fvSchemes dictionary
55 functions • As usual, at the bottom of the controlDict dictionary file 17 ddtSchemes • In this case, for time discretization (ddtSchemes) we are
56 {
we define the functionObjects (lines 55-236). 18
19
{
default Euler;
using the Euler method.
178 forceCoeffs_object 20 }
179 { • Of special interest is the functionObject 21 • For gradient discretization (gradSchemes) we are using the
188
189
type forceCoeffs;
functionObjectLibs ("libforces.so");
forceCoeffs_object. 22
23
gradSchemes
{
leastSquares method.
190 patches (cylinder); 29 default cellLimited leastSquares 1;
191 • As we changed the domain dimensions and the inlet 34 } • For the discretization of the convective terms (divSchemes)
192
193
pName p;
Uname U;
velocity we need to update the reference values (lines 204- 35
36 divSchemes
we are using linearUpwind interpolation with no slope limiters
194 //rhoName rhoInf; 206). 37 { for the term div(phi,U).
195 rhoInf 1.205; 38 default none;
196
197 //// Dump to file
• It is also important to update the reference density (line 39
40
div(phi,U) Gauss linearUpwindV default;
• For the terms div(phi,K) (kinetic energy) and div(phi,h)
198 log true; 195). 41 div(phi,K) Gauss linear; (enthalpy) we are using linear interpolation method with no
199 42 div(phi,h) Gauss linear;
200 CofR (0.0 0 0); 43 slope limiters.
201 liftDir (0 1 0); 44 div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
202 dragDir (1 0 0); 45 } • For the term div(((rho*nuEff)*dev2(T(grad(U))))) we are
203 pitchAxis (0 0 1); 46
204 magUInf 1.5; 47 laplacianSchemes using linear interpolation (this term is related to the turbulence
205
206
lRef 0.001;
Aref 0.000002;
48
49
{
default Gauss linear limited 1;
modeling).
207 50 }
208 outputControl timeStep; 51 • For the discretization of the Laplacian (laplacianSchemes
209
210
outputInterval
}
1; 52
53
interpolationSchemes
{
and snGradSchemes) we are using the Gauss linear limited
54 default linear; 1 method.
235 55 }
56
236 };
57 snGradSchemes
• This method is second order accurate.
58 {
59 default limited 1;
60 }
274 275
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 the pressure (p) we are using the PCG method with 88 • The PIMPLE sub-dictionary contains entries related to the
18
20
{
p
an absolute tolerance of 1e-6 and a relative tolerance relTol 89
90
PIMPLE
{
pressure-velocity coupling (in this case the PIMPLE method).
21 { of 0.01. 91 momentumPredictor yes;
22 solver PCG; 92 nOuterCorrectors 1; • Setting the keyword nOuterCorrectors to 1 is equivalent to
23
24
preconditioner
tolerance
DIC;
1e-06;
• The entry pFinal refers to the final correction of the PISO 93
94
nCorrectors 2;
nNonOrthogonalCorrectors 1;
running using the PISO method.
25 relTol 0.01; loop. Notice that we are using macro expansion ($p) to copy 95 rhoMin 0.5;
26 minIter 2; 96 rhoMax 2.0; • Hereafter we are doing 2 PISO correctors (nCorrectors) and
the entries from the sub-dictionary p.
27
46
}
pFinal
97 }
1 non-orthogonal corrections (nNonOrthogonalCorrectors).
47 { • To solve U and UFinal (U.*) we are using the solver
48 $p; • In lines 95-96 we set the minimum and maximum physical
PBiCGStab with an absolute tolerance of 1e-8 and a relative
49 relTol 0;
values of rho (density).
50
51 }
minIter 2;
tolerance relTol of 0.
53 "U.*" • If we increase the number of nCorrectors and
54 { • To solve hFinal (enthalpy) we are using the solver
nNonOrthogonalCorrectors we gain more stability but at a
55 solver PBiCGStab;
PBiCGStab with an absolute tolerance of 1e-8 and a relative
56 preconditioner DILU; higher computational cost.
57 tolerance 1e-08; tolerance relTol of 0.
58 relTol 0;
• The choice of the number of corrections is driven by the
59 minIter 2;
• To solve rho and rhoFinal (rho.*) we are using the diagonal
60 } quality of the mesh and the physics involve.
74 hFinal solver (remember rho is found from the equation of state, so
75 {
76 solver PBiCGStab; this is a back-substitution). • You need to do at least one PISO loop (nCorrectors).
77 preconditioner DILU;
78 tolerance 1e-08; • FYI, solving for the velocity is relative inexpensive, whereas
79 relTol 0;
80 minIter 2; solving for the pressure is expensive.
81 }
83 "rho.*" • Be careful with the enthalpy, it might cause oscillations.
84 {
85 solver diagonal;
86 }
87 }
276 277
Flow past a cylinder – From laminar to turbulent flow Flow past a cylinder – From laminar to turbulent flow
Running the case – Using a compressible solver Running the case
• You will find this tutorial in the directory $PTOFC/101OF/vortex_shedding/c24
Using a compressible solver
• Feel free to use the Fluent mesh or the mesh generated with blockMesh. In this case we will use • In step 3 we scale the mesh.
blockMesh.
• In step 4 we use the utility renumberMesh to make the linear system more diagonal
• To run this case, in the terminal window type:
dominant, this will speed-up the linear solvers.
1. $> foamCleanTutorials • In step 5 we run the simulation and save the log file. Notice that we are sending the
$> blockMesh job to background.
2.
• In step 6 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. As the
3. $> transformPoints –scale ‘(0.001 0.001 0.001)’
job is running in background, we can launch this utility in the same terminal tab.
4. $> renumberMesh -overwrite • In step 7 we use the gnuplot script scripts0/plot_coeffs to plot the force
5. $> rhoPimpleFoam | tee log coefficients on-the-fly. Besides monitoring the residuals, is always a good idea to
$> pyFoamPlotWatcher.py log monitor a quantity of interest. Feel free to take a look at the script and to reuse it.
6. • In step 8 we use the utility MachNo to compute the Mach number.
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
Courant Number mean: 0.1280224248 max: 0.9885863338 Courant number
deltaT = 3.816512052e-05 Time step
Time = 0.3
diagonal: Solving for rho, Initial residual = 0, Final residual = 0, No Iterations 0 Solving for density
• In the directory:
PIMPLE: iteration 1 (rho)
DILUPBiCG: Solving for Ux, Initial residual = 0.003594731129, Final residual = 3.026673755e-11, No Iterations 5
DILUPBiCG: Solving for Uy, Initial residual = 0.01296036298, Final residual = 1.223236662e-10, No Iterations 5
DILUPBiCG: Solving for h, Initial residual = 0.01228951539, Final residual = 2.583236461e-09, No Iterations 4 h residuals
DICPCG: Solving for p, Initial residual = 0.01967621449, Final residual = 8.797612158e-07, No Iterations 77
DICPCG: Solving for p, Initial residual = 0.003109422612, Final residual = 9.943030465e-07, No Iterations 69
diagonal: Solving for rho, Initial residual = 0, Final residual = 0, No Iterations 0
time step continuity errors : sum local = 6.835363016e-11, global = 4.328592697e-12, cumulative = 2.366774797e-09
rho max/min : 1.201420286 1.201382023 pFinal
DICPCG: Solving for p, Initial residual = 0.003160602108, Final residual = 9.794177338e-07, No Iterations 69
$PTOFC/101OF/vortex_shedding
DICPCG: Solving for p, Initial residual = 0.0004558492254, Final residual = 9.278622052e-07, No Iterations 58
diagonal: Solving for rho, Initial residual = 0, Final residual = 0, No Iterations 0 Solving for density (rhoFinal)
time step continuity errors : sum local = 6.38639685e-11, global = 1.446434866e-12, cumulative = 2.368221232e-09
rho max/min : 1.201420288 1.201381976 Max/min density values
ExecutionTime = 480.88 s ClockTime = 490 s
Roadmap
Module 2
1. CFD simulation workflow
CFD simulation workflow – Solid modeling
2. Solid modeling – Preliminaries
3. Solid modeling using Onshape
284 285
CFD simulation workflow CFD simulation workflow
GEOMETRY
MESH
• Usually, we find these issues when importing or exporting the geometry from/to
different formats.
290 291
Original Geometry
Defeatured Geometry
Sew faces
Align faces
Delete overlapping faces
Connect/disconnect edges
292 293
Solid modeling – Preliminaries Roadmap
A few open-source/free CAD/solid modeling applications
• On-shape: it is a full cloud based 3D CAD system. It runs in a web browser and on any device
with a working web browser. It has the same capabilities of commercial CAD systems. You can
create a free account and start to use it immediately. http://www.onshape.org/
• Salome: it is a history based CAD tool (but not a 100% parametric). It has quite extensive
capabilities for creation and manipulation of solid geometries. Its capabilities mirror those of
commercial CAD systems. http://www.salome-platform.org/
• Autodesk 360 fusion: it is a full desktop 3D CAD system. It runs in windows and Mac. It is free
for student, enthusiasts, hobbyists, and startups. http://www.autodesk.com/products/fusion-
1. CFD simulation workflow
360/overview
2. Solid modeling – Preliminaries
• Free-CAD: it is a history based CAD tool (parametric design). Light CAD software, good for not
very complicated mechanical designs. http://sourceforge.net/apps/mediawiki/free-cad/ 3. Solid modeling using Onshape
• OpenVSP: it is a parametric aircraft geometry tool. It allows users to create a 3D model of an
aircraft defined by common engineering parameters. http://www.openvsp.org/
• Openscad: it is a 3D programming modeling tool. It reads in a script file that describes the
object and renders the 3D model from this script file. http://www.openscad.org/
• DesignSpark mechanical: it is a full CAD/solid modeling software. It is distributed for free.
This particular one will blow your mind, the only drawback is that it only runs in windows.
https://www.rs-online.com/designspark/mechanical-software
294 295
(simultaneous editing).
• It runs in any device with a working web browser.
Enter to sketch mode
• It is freely available for educational use.
• To start using onshape register at: https://cad.onshape.com/
Feature list
Parts list
3D area
296 Document tabs 297
Solid modeling using Onshape Solid modeling using Onshape
• Mouse interaction in the 3D area (it can be configure in the preference area). • Parametric modeling and feature based modeling are crucial components in the
design experience.
Mouse interaction in the
3D viewer
• In onshape you will find the following features:
Feature toolbar:
Selection
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.
302 303
Sweep feature
Origin
306 307
Solid name.
Right click to rename
or view the properties
New plane
Use this point to create Sketch this circle in the newly created plane
the new plane
310 311
314 315
Module 3
• Experimenting with dimension schemes is one of the best ways to improve your
understanding of design intent.
• Finally, feel free to visit our youtube channel where you will find a few solid modeling
videos:
https://www.youtube.com/channel/UCNNBm3KxVS1rGeCVUU1p61g
Meshing preliminaries – Mesh quality
assessment – Meshing in OpenFOAM®
316 317
Before we begin Before we begin
• OpenFOAM® comes with the following meshing applications:
By the end of this module, you will realize that
• blockMesh
You will use snappyHexMesh to mesh the sphinx
• snappyHexMesh
• foamyHexMesh
• foamyQuadMesh You will use blockMesh to mesh the pyramids
318 319
322 323
inlet outlet
top
left right
airplane
• In the meshing world, there are many cell types. Just to name a few: tetrahedrons,
pyramids, hexahedrons, prisms, polyhedral.
5. blockMesh guided tutorials.
• Each cell type has its very own properties when it comes to approximate the gradients 6. Mesh generation using snappyHexMesh.
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 7. snappyHexMesh guided tutorials.
conditions.
8. Mesh conversion
• However, this does not mean that tetra/poly cells are not good.
• What cell type do I use? It is up to you, at the end of the day the overall quality of the 9. Geometry and mesh manipulation utilities
final mesh should be acceptable and your mesh should resolve the physics
326 327
328 329
What is a good mesh? What is a good mesh?
• No single standard benchmark or metric exists that can effectively assess Mesh quality metrics. Mesh orthogonality
the quality of a mesh, but the user can rely on suggested best practices.
• Mesh orthogonality is the angular deviation of the vector S (located at the face center
• Hereafter, we will present the most common mesh quality metrics: f ) from the vector d connecting the two cell centers P and N. In this case is .
• Orthogonality. • Affects the gradient of the face center f.
• Skewness. • It adds numerical diffusion to the solution.
• Aspect Ratio. • It mainly affects the diffusive terms.
• 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,
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.
330 331
332 333
What is a good mesh? What is a good mesh?
Mesh quality metrics. Element type close to the walls - Cell/Flow alignment
Mesh quality metrics. Smoothness
• Smoothness, also known as expansion rate, growth factor or uniformity, defines the • Hexes, prisms, and quadrilaterals can be stretched easily to resolve boundary layers
transition in size between contiguous cells. without losing quality.
• Large transition ratios between cells add diffusion to the solution. • Triangular and tetrahedral meshes have inherently larger truncation error.
• Ideally, the maximum change in mesh spacing should be less than 20%: • Less truncation error when faces aligned with flow direction and gradients.
Flow direction
Hexa
23rd IMR Meshing Maestro Contest Winner
Zhoufang Xiao , Jianjing Zheng, Dawei Zhao, Lijuan Zeng, Jianjun Chen, Yao Zheng
Center for Engineering & Scientific Computation, Zhejiang University, China.
Year 336 http://www.sandia.gov/imr/MeshingContest.html 337
What is a good mesh? What is a good mesh?
Striving for quality Striving for quality
• And by the way, you can combine all cell types to get a hybrid mesh. • Hexes, prisms, and quadrilaterals can be easily aligned with the flow.
• They can also be stretched to resolve boundary layers without losing much quality.
• Triangular and tetrahedral meshes can easily be adapted to any kind of geometry.
The mesh generation process is almost automatic.
• Triangular and tetrahedral meshes have inherently larger truncation error.
• Tetrahedral meshes normally need more computing resources during the solution
stage. But this can be easily offset by the time saved during the mesh generation
stage.
• Increasing the cells count will likely improve the solution accuracy, but at the cost of a
higher computational cost. But attention, a finer mesh does not mean a better mesh.
• To keep cell count low, use non-uniform meshes to cluster cells only where they are
needed. Use local refinements and solution adaption to further refine only on
selected areas.
• In boundary layers, quads, hexes, and prisms/wedges cells are preferred over
triangles, tetrahedrons, or pyramids.
• If you are not using wall functions (turbulence modeling), the mesh next to the walls
should be fine enough to resolve the boundary layer flow. Have in mind that this will
338 rocket the cell count and increase the computing time. 339
340 341
Roadmap Mesh quality assessment in OpenFOAM®
Mesh quality metrics in OpenFOAM®
1. Meshing preliminaries • In the file primitiveMeshCheck.C located in the directory
$WM_PROJECT_DIR/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCheck/
you will find the quality metrics used in OpenFOAM®. Their maximum (or minimum) values are
2. What is a good mesh? defined as follows:
344 345
Mesh quality assessment in OpenFOAM® Mesh quality assessment in OpenFOAM®
Checking the mesh quality in OpenFOAM® Visualizing the failed sets in OpenFOAM®
• Mesh topology and patch topology errors must be repaired.
• You can load the failed sets directly within
• You will be able to run with mesh quality errors such as skewness, aspect ratio, paraFoam.
minimum face area, and non-orthogonality.
• Remember, you will need to create the sets. To
• But remember, they will severely tamper the solution accuracy, might give you strange do so just run the checkMesh utility.
results, and eventually can made the solver blow-up.
• If there are problems in the mesh, checkMesh
• Unfortunately, checkMesh does not repair these errors.
will automatically save the sets in the directory
• You will need to check the geometry for possible errors and generate a new mesh. constant/polyMesh/sets
• You can visualize the failed sets directly in paraFoam . • In paraFoam, simply select the option Include
• Alternatively, you can use the utility foamToVTK to convert the failed sets to VTK Sets and then select the sets you want to
format. visualize.
• This method only works with paraFoam.
• When working with large meshes we prefer to
convert the faulty sets to VTK format using
foamToVTK. Failed sets
346 347
Mesh stats
• $> foamToVTK -set_type name_of_sets points:
faces:
81812
902132
internal faces: 871012
cells: 443286
faces per cell: 4 Mesh stats
boundary patches: 9
where set_type is the type of sets (faceSet, cellSet, pointSet, surfaceFields) and point zones: 0
name_of_sets is the name of the set in the directory constant/polyMesh/sets face zones:
cell zones:
1
1
(highAspectRatioCells, nonOrthoFaces, wrongOrientedFaces, skewFaces, Overall number of cells of each type:
unusedPoints, and so on). hexahedra: 0
prisms: 0
• At the end, foamToVTK will create a directory named VTK, where you will find the wedges:
pyramids:
0
0 Number of each type of cells
failed faces/cells/points in VTK format. tet wedges:
tetrahedra:
0
443286
polyhedra: 0
• At this point you can use paraview/paraFoam to open the VTK files and visualize
the failed sets. Checking topology...
Boundary definition OK. Checking mesh topology
Cell to face addressing OK.
***Unused points found in the mesh, number unused by faces: 16 number unused by cells: 16
<<Writing 16 unused points to set unusedPoints
Upper triangular ordering OK.
Face vertices OK.
Number of regions: 1 (OK). Unused points found in the mesh
In this case they do not harm the solution
They can be removed using topoSet and subsetMesh
348 349
Mesh quality assessment in OpenFOAM® Mesh quality assessment in OpenFOAM®
Checking mesh quality in OpenFOAM® Visualization of faulty sets in paraFoam
• Sample checkMesh output, • You will find this case ready to use in the directory,
$PTOFC/mesh_quality_manipulation/M1_wingbody
Checking patch topology for multiply connected surfaces...
Patch Faces Points Surface topology • To run the case, just follow the instructions in the README.FIRST files.
FAIRING 1267 727 ok (non-closed singly connected)
FUSELAGE 3243 1774 ok (non-closed singly connected)
WING 15313 7706 ok (non-closed singly connected)
INLET 272 160 ok (non-closed singly connected)
OUTLET 272 160 ok (non-closed singly connected) Boundary patches
SYMM 6280 3324 ok (non-closed singly connected)
FARFIELD 3136 1645 ok (non-closed singly connected)
NOSE 76 49 ok (non-closed singly connected)
COCKPIT 1261 670 ok (non-closed singly connected)
Checking geometry...
Overall domain bounding box (-15000 -7621.0713 -7396.4536) (30048.969 0 7446.8442)
Mesh has 3 geometric (non-empty/wedge) directions (1 1 1)
Mesh has 3 solution (non-empty) directions (1 1 1)
Mesh bounding box
Boundary openness (-4.2298633e-18 8.0240802e-16 4.013988e-16) OK.
Max cell openness = 4.8098963e-16 OK.
Max aspect ratio = 29.575835 OK. Aspect ratio
Minimum face area = 0.0066721253. Maximum face area = 1037224.8. Face area magnitudes OK.
Min volume = 0.00050536842. Max volume = 3.2500889e+08. Total volume = 5.0960139e+12. Cell volumes OK.
Mesh non-orthogonality Max: 86.939754 average: 17.939523 High non-orthogonality
*Number of severely non-orthogonal (> 70 degrees) faces: 3168. But we still can run the simulation
Non-orthogonality check OK.
<<Writing 3168 non-orthogonal faces to set nonOrthoFaces
Face pyramids OK.
Max skewness = 2.5719979 OK. Skewness
Coupled point location match (average 0) OK.
Failed 1 mesh checks. The fact that one check failed does not mean that you can not run the simulation
End 350 Non orthogonal faces (green spheres) and unused points (yellow spheres) 351
blockMesh
1. Meshing preliminaries • “blockMesh is a multi-block mesh generator.”
• For simple geometries, the mesh generation utility blockMesh can be used.
2. What is a good mesh?
• The mesh is generated from a dictionary file named blockMeshDict
3. Mesh quality assessment in OpenFOAM® located in the system directory.
• The meshing tool generates high quality meshes, it is the tool to use for very
4. Mesh generation using blockMesh. simple geometries. As the complexity of the geometry increases, the effort
5. blockMesh guided tutorials. and time required to setup the dictionary increases a lot.
• Usually the background mesh used with snappyHexMesh consist of a single
6. Mesh generation using snappyHexMesh. rectangular block, therefore blockMesh can be used with no problem.
7. snappyHexMesh guided tutorials. • It is highly recommended to create a template of the dictionary
blockMeshDict that you can change according to the dimensions of your
8. Mesh conversion domain.
9. Geometry and mesh manipulation utilities • You can also use m4 or Python scripting to automate the whole process.
352 353
Mesh generation using blockMesh Mesh generation using blockMesh
blockMesh workflow
blockMesh
• To generate a mesh with blockMesh, you will need to define the vertices, block
v connectivity and number of cells in each direction.
• To assign boundary patches, you will need to define the faces connectivity
354 355
358 359
360 361
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
• Then we compute the number of cells to be used in each
20 xmax 1; 20 xmax 1;
of cells (lines 38-40).
21
22
ymin
ymax
0;
1;
direction (lines 38-40). 21
22
ymin
ymax
0;
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
the number of cells needed in each direction according to 33
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 );
362 363
364 365
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 );
366 367
368 369
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 (
backAndFront
91 faces • In lines 104-11 we define the patch bottom. 125 (0 3 2 1)
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 }
370 371
372 373
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);
defaultFaces
31
32
nFaces
startFace
400;
23200;
boundary condition (or numerical boundary condition). 31
32
nFaces
startFace
400;
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
46
nFaces
startFace
400;
24000;
dictionary blockMeshDict in the section boundary. 45
46
nFaces
startFace
400;
24000;
47 } 47 }
48 front 48 front
49 { • You can change the name if you do not like it. Do not use 49 {
50
51
type
inGroups
wall;
1(wall);
strange symbols or white spaces. 50
51
type
inGroups
wall;
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 ) 374 62 ) 375
1. $> paraFoam -block • From this point on, please follow me.
• We are all going to work at the same pace.
• Remember, $PTOFC is pointing to the path where you
• You can run the rest of the cases following the same steps. unpacked the tutorials.
380 381
blockMesh guided tutorials blockMesh guided tutorials
What are we going to do? The blockMeshDict dictionary.
• We will use this case to study how to change mesh grading (growth rate).
No grading
• You can use this dictionary as a blockMeshDict template that you can change
automatically according to the dimensions of your domain and the desired cell 61 blocks
spacing and growth rate. 62
63
(
hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1)
88 );
Mesh grading
• To control mesh grading, we use the simpleGrading keyword.
• Setting the values to (1 1 1) means no grading (uniform mesh).
• A value different from 1 will add grading to the edge, that is, it will cluster more cells
towards one extreme of the block.
Mesh with no grading Mesh with grading • Let us take a look at a 2D mesh.
382 383
61 blocks 61 blocks
62 ( 62 (
63 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (0.125 8 1) 63 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (0.125 0.125 1)
88 ); 88 );
Stretching in the X direction (edge 0-1) Stretching in the X direction (edge 0-1)
61 blocks 61 blocks
62 ( 62 (
63 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (8 8 1) 63 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (8 0.125 1)
88 ); 88 );
Stretching in the X direction (edge 0-1) Stretching in the X direction (edge 0-1)
384 385
blockMesh guided tutorials blockMesh guided tutorials
The blockMeshDict dictionary. The blockMeshDict dictionary.
Multi-grading of a block
Multi-grading of a block 61
62
blocks
( • Let us use multi-grading in the X-direction (lines 70-
64
74).
• Using a single grading to describe mesh 65
66
hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells)
simpleGrading
• First, we split the block into 3 divisions in the X-
grading permits only one-way grading of 67
68
(
// x-direction expansion ratio
direction representing 20% or 0.2 (division 1), 60% or
70 (
the block. BLOCK 0 BLOCK 1 71 (0.2 0.25 8) //Division 1 0.6 (division 2), and 20% or 0.2 (division 3) of the
72 (0.6 0.50 1) //Division 2
block length.
• For example, to mesh the square cavity 73
74 )
(0.2 0.25 0.125) //Division 3
386 387
388 389
blockMesh guided tutorials blockMesh guided tutorials
What are we going to do?
• Let us take a close look to a blockMeshDict dictionary to • We will use this case to take a close look at a blockMeshDict dictionary.
study how to create multiple blocks. • We will study how to work with multiple blocks.
• We will use the square cavity case. • When working with multiples blocks, we need to deal with the common face between
• You will find this case in the directory: blocks. If we do not connect these blocks, blockMesh will create a boundary patch
and we will need to assign a boundary condition to this patch.
• When we connect the blocks, blockMesh will create an internal face (therefore we
$PTOFC/101BLOCKMESH/C3 do not need to assign a boundary condition to the face).
• There are two ways to connect blocks, using face matching and face merging.
Hereafter we are going to study face merging.
394 395
Master Slave
396 397
blockMesh guided tutorials blockMesh guided tutorials
The blockMeshDict dictionary. The extrudeMeshDict dictionary.
• The utility extrudeMesh will create a 2D mesh by projecting the source patch into the exposed
73 blocks
74 ( patch.
75 hex (0 1 2 3 4 5 6 7) ($xcells $ycells $zcells) simpleGrading (1 1 1) //BLOCK 0
76
77
//hex (8 9 10 11 12 13 14 15) ($xcells $ycells $zcells) simpleGrading (1 1 1)
hex (8 9 10 11 12 13 14 15) (40 $ycells $zcells) simpleGrading (1 1 1) //BLOCK 1
• To create the 2D mesh, you will need to use 1 layer (nLayers).
78 );
• It is also recommended to set the extrusion thickness to 1.
402 403
133 );
406 407
410 411
54
69 edges • In lines 69-86 we define arc edges.
70 (
55 blocks
56 (
71
72
//block0 arc
arc 1 2 (0 1 0)
• In lines 88-129 we define the boundary patches.
57 //block0 73 arc 5 6 (0 1 100)
58
59
hex (0 3 2 1 4 7 6 5)
//block1
($xcells $ycells $zcells) simpleGrading (1 $stretch 1) 74 • In lines 91-102 we define the patch inlet. Notice that this
75 //block1 arc
60 hex (3 8 9 2 7 10 11 6) ($xcells $ycells $zcells) simpleGrading (1 $stretch 1) 76 arc 2 9 (1 0 0) boundary patch has five faces.
61 //block2 77 arc 6 11 (1 0 100)
62 hex (8 12 13 9 10 14 15 11) ($xcells $ycells $zcells) simpleGrading (1 $stretch 1) 78
63 //block3 79 //block2 arc
64 hex (12 0 1 13 14 4 5 15) ($xcells $ycells $zcells) simpleGrading (1 $stretch 1) 80 arc 9 13 (0 -1 0)
65 //block4 81 arc 11 15 (0 -1 100)
66 hex (0 12 8 3 4 14 10 7) ($xcells1 $ycells1 $zcells1) simpleGrading (1 1 1) 82
67 ); 83 //block3 arc
84 arc 1 13 (-1 0 0)
85 arc 5 15 (-1 0 100)
86 );
87
88 boundary
89 (
• In lines 55-67, we define all the blocks that made up the 90
91 inlet
O-grid topology. 92 {
93 type patch;
• Notice that we are creating five blocks. 94
95
faces
(
96 (0 1 2 3)
• We also define the number of cells of each block and 97 (2 3 8 9)
the grading. 98
99
(8 9 13 12)
(13 12 0 1)
100 (0 3 8 12)
• As we are using face matching, the grading and 101 );
number of cells in the common faces need to be the 102
103
}
same.
412 413
blockMesh guided tutorials blockMesh guided tutorials
The blockMeshDict dictionary. The final mesh should looks like this one
414 415
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. blockMesh guided tutorials.
6. Mesh generation using snappyHexMesh.
7. snappyHexMesh guided tutorials.
8. Mesh conversion
9. Geometry and mesh manipulation utilities
416 417
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow snappyHexMesh workflow – Background mesh
• To generate a mesh with snappyHexMesh we proceed as follows: • The background or base mesh can be generated using blockMesh or an
external mesher.
• Generation of a background or base mesh.
• Geometry definition.
• The following criteria must be observed when creating the background
mesh:
• Generation of a castellated mesh or cartesian mesh.
• The mesh must consist purely of hexes.
• Generation of a snapped mesh or body fitted mesh.
• The cell aspect ratio should be approximately 1, at least near the
• Addition of layers close to the surfaces or boundary layer meshing.
STL surface.
• Check/enforce mesh quality.
• There must be at least one intersection of a cell edge with the
blockMesh or external mesher STL surface.
blockMesh or external mesher
snappyHexMesh
snappyHexMesh
418 419
Background mesh Geometry (STL file) Background mesh Geometry (STL file)
snappyHexMesh snappyHexMesh
420 421
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow snappyHexMesh workflow
• All the volume and surface refinement is done in reference to the
background or base mesh.
and so on …
Base cell – RL 0 RL 1 RL 2
* RL = refinement level
Note: • The process of generating a mesh using snappyHexMesh will be described using this figure.
• In 2D each quad is subdivided in 4
quads. • The objective is to mesh a rectangular shaped region (shaded grey in the figure) surrounding an object
• In 3D each hex is subdivided in 8 described by a STL surface (shaded green in the figure).
hexes. • This is an external mesh (e.g. for external aerodynamics). You can also generate an internal mesh (e.g. flow in
a pipe).
422 423
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.
424 425
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
snappyHexMesh workflow snappyHexMesh workflow
426 427
• Open the dictionary snappyHexMeshDict with your favorite text editor (we use
• Let us study the snappyHexMesh dictionary in gedit).
details. • The dictionary snappyHexMeshDict consists of five main sections:
432 433
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us explore the snappyHexMeshDict dictionary. Let us explore the snappyHexMeshDict dictionary.
castellatedMesh true; //or false castellatedMesh true; //or false • Have in mind that there are more than 70
snap true; //or false snap true; //or false
addLayers true; //or false addLayers true; //or false parameters to control in
snappyHexMeshDict dictionary.
geometry geometry
{ {
... ... • Adding the fact that there is no native GUI, it
... ... can be quite tricky to control the mesh
} }
generation process.
castellatedMeshControls castellatedMeshControls
{ {
... ... • Nevertheless, snappyHexMesh generates
... ...
} } really good hexa dominant meshes.
snapControls snapControls
{ { • Hereafter, we will only comment on the most
... ...
... ...
important parameters.
} }
• The snappyHexMesh dictionary is made up of five sections, namely:
addLayersControls geometry, castellatedMeshControls, snapControls, addLayersControls • The parameters that you will find in the
{ addLayersControls and meshQualityControls. Each section
controls a step of the meshing process.
{ snappyHexMeshDict dictionaries distributed
... ...
... ... with the tutorials, in our opinion are robust and
} • In the first three lines we can turn off and turn on the different }
meshing steps. For example, if we want to generate a body fitted will work most of the times.
meshQualityControls mesh with no boundary layer we should proceed as follows: meshQualityControls
{ {
... castellatedMesh true; ...
... snap true; ... May be located In a separated file
} addLayers false; }
434 435
writeFlags
• system/meshQualityDict
(
// write volScalarField with cellLevel for • At the end of the dictionary you will find the sections: debugFlags • system/blockMeshDict
// postprocessing and writeFlags
scalarLevels • constant/triSurface/wolfExtruded.stl
• By default they are commented. If you uncomment them you will
// write cellSets, faceSets of faces in layer enable debug information. • constant/triSurface/wolfExtruded.eMesh
layerSets
• debugFlags and writeFlags will produce a lot of outputs that you
// write volScalarField for layer coverage can use to post process and troubleshoot the different steps of
layerFields the meshing process.
); • The file wolfExtruded.eMesh is generated after using the utility
surfaceFeatureExtract, which reads the dictionary surfaceFeatureExtractDict.
446 447
• To generate the mesh, in the terminal window type: • In the case directory you will find the time folders 1, 2, and 3, which contain
the castellated mesh, snapped mesh and boundary layer mesh respectively.
1. $> foamCleanTutorials In this case, snappyHexMesh automatically saved the intermediate steps.
2. $> blockMesh • Before running the simulation, remember to transfer the solution from the
3. $> surfaceFeatureExtract latest mesh to the directory constant/polyMesh, in the terminal type:
4. $> snappyHexMesh
5. $> checkMesh –latestTime 1. $> cp 3/polyMesh/* constant/polyMesh
2. $> rm –rf 1
• To visualize the mesh, in the terminal window type: $> rm –rf 2
3.
• $> paraFoam $> rm –rf 3
4.
5. $> checkMesh –latestTime
• Remember to use the VCR controls in paraView/paraFoam to visualize the
mesh intermediate steps.
448 449
Mesh generation using snappyHexMesh Mesh generation using snappyHexMesh
Let us generate the mesh of the wolf dynamics logo. The constant/polyMesh/boundary file
• At this point, we have a valid mesh to run a simulation.
• Have in mind that before running the simulation you will need to set the boundary and initial
• If you want to avoid the additional steps of transferring the final mesh to the conditions in the directory 0.
directory constant/polyMesh by not saving the intermediate steps, you • Let us talk about the constant/polyMesh/boundary file,
can proceed as follows: • First at all, this file is automatically generated after you create the mesh or you convert it
from a third party format.
• In this file, the geometrical information related to the base type patch of each boundary of
• $> snappyHexMesh –overwrite the domain is specified.
• The base type boundary condition is the actual surface patch where we are going to apply
a primitive type boundary condition (or numerical boundary condition).
• When you proceed in this way, snappyHexMesh automatically saves the • The primitive type boundary condition assign a field value to the surface patch (base
final mesh in the directory constant/polyMesh. type).
• Have in mind that you will not be able to visualize the intermediate steps. • You define the numerical type patch (or the value of the boundary condition), in the
directory 0 or time directories.
• Also, you will not be able to restart the meshing process from a saved state • The name and base type of the patches was defined in the dictionaries blockMeshDict
(castellated or snapped mesh). and snappyHexMeshDict.
• You can change the name if you do not like it. Do not use strange symbols or white
• Unless it is strictly necessary, from this point on we will not save the
spaces.
intermediate steps. • You can also change the base type. For instance, you can change the type of the patch
450 maxY from wall to patch. 451
55 maxZ
• When generating the mesh using OpenFOAM®, it is extremely important to
Name and type of the surface patches
56
57
{
type wall; start from a clean case directory.
58 inGroups 1(wall); • The name and base type of the patch is given by the user.
59 nFaces 400;
60 startFace 466399;
• In this case the name and base type was assigned in the
61
62
}
wolf_wall
Name
dictionaries blockMeshDict and snappyHexMeshDict.
• To clean all the case directory, in the terminal type:
63 {
64 type wall; Type
• You can change the name if you do not like it. Do not use
65
66
inGroups
nFaces
1(wall);
400;
strange symbols or white spaces.
• $> foamCleanTutorials
67 startFace 466799;
68 }
69 sphere
nFaces • You can also change the base type. For instance, you can
70
71
{
type empty; startFace change the type of the patch maxY from wall to patch. • To only erase the mesh information, in the terminal type:
72 inGroups 1(wall);
73 nFaces 400;
•
74 startFace 467199;
75
76
}
sphere_slave nFaces and startFace keywords
$> foamCleanPolyMesh
77 {
78 type wall; • Unless you know what you are doing, you do not
79
80
inGroups
nFaces
1(wall);
400; need to change this information. • If you are planning to start the meshing from a previous saved state, you do
81 startFace 467599;
82
83 )
}
• Basically, this is telling you the starting face and ending face not need to clean the case directory.
of the patch.
• This information is created automatically when generating • Before proceeding to compute the solution, remember to always check the
the mesh or converting the mesh.
quality of the mesh.
454 455
$PTOFC/101SHM/M1_cyl/C1 Sphere with no edge refinement Cylinder with edge refinement Cylinder with no edge refinement
• If the geometry has sharp angles and you want to resolve those edges, you should use edge
refinement.
• From this point on, please follow me.
• In the left figure there is no need to use edge refinement as there are no sharp angles.
• We are all going to work at the same pace.
• In the mid figure we used edge refinement to resolve the sharp angles.
• Remember, $PTOFC is pointing to the path where you • In the right figure we did not use edge refinement, therefore we did not resolve well the sharp
unpacked the tutorials. angles.
458 459
...
...
...
} 460 461
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• How do we control surface refinement?
How resolveFeatureAngle works? • In the file snappyHexMeshDict, look for the following entry:
...
...
...
0: mark the whole surface for refinement
180: do not mark any STL face for refinement }
462 463
castellatedMeshControls
geometry {
{ ...
... ...
... ...
...
refinementRegions
refinementBox Name of refinement region { Name of the region
{ refinementBox created in the geometry section
type searchableBox; Geometrical entity type. {
min ( -2 -2 -2); This is the zone where we mode inside; Type of refinement (inside,
max ( 2 2 2); want to apply the refinement levels ((1e15 1)); outside, or distance mode)
} }
}
... Refinement level
Dimensions of geometrical entity ...
...
... ... Distance from the surface
}; ... A large value covers the whole region
}
464 465
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 0 Explicit feature edge refinement level 0 Explicit feature edge refinement level 4
resolveFeatureAngle 110 resolveFeatureAngle 60 resolveFeatureAngle 60 resolveFeatureAngle 60
Surface based refinement level (2 2) Surface based refinement level (2 2) Surface based refinement level (2 2) Surface based refinement level (2 2)
• To control edges capturing you can decrease the value of resolveFeatureAngle. • To control edges refinement level, you can change the value of the explicit feature
• Be careful, this parameter also controls curvature refinement, so if you choose a low edge refinement level.
value you also will be adding a lot of refinement on the surface.
466 467
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 6 Explicit feature edge refinement level 0 Explicit feature edge refinement level 0 Explicit feature edge refinement level 4
resolveFeatureAngle 5 resolveFeatureAngle 5 resolveFeatureAngle 60 resolveFeatureAngle 60
Surface based refinement level (2 4) Surface based refinement level (2 4) Surface based refinement level (2 4) Surface based refinement level (2 2)
• To control edges refinement level, you can change the value of the explicit feature • To control surface refinement level, you can change the value of the surface based
edge refinement level. refinement level.
• The first digit controls the global surface refinement level and the second digit
468
controls the curvature refinement level. 469
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• Let us explore the dictionary surfaceFeatureExtractDict used by the
Effect of various parameters on edge capturing and surface refinement utility surfaceFeatureExtract.
• This utility will extract surface features (sharp angles) according to an angle
criterion (includedAngle).
extractionMethod extractFromSurface;
extractFromSurfaceCoeffs
{
Angle criterion
includedAngle 150;
to extract features
}
Explicit feature edge refinement level 0 Explicit feature edge refinement level 0
resolveFeatureAngle 60 resolveFeatureAngle 5 subsetFeatures
{
Surface based refinement level (2 4) Surface based refinement level (2 4) nonManifoldEdges yes;
openEdges yes;
}
• To control surface refinement due to curvature together with control based surface If you want to save
writeObj yes;
refinement level, you can change the value of resolveFeatureAngle, and surface the .obj files Features edges
470 471
extractionMethod extractFromSurface;
angle
extractFromSurfaceCoeffs
{
Angle criterion
includedAngle 150;
to extract features
} STL
subsetFeatures includedAngle
{
nonManifoldEdges yes;
openEdges yes;
} Mark edges whose adjacent surface normals
are at an angle less than includedAngle
writeObj yes; If you want to save
the .obj files 0: selects no edges
} 180: selects all edge
472 473
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement. 3D Cylinder with edge refinement.
• In this case we are going to generate a body fitted mesh with edge refinement. This is an
external mesh. • Let us generate the mesh, in the terminal window type:
• These are the dictionaries and files that will be used.
1. $> foamCleanTutorials
• system/snappyHexMeshDict
2. $> surfaceFeatureExtract
• system/surfaceFeatureExtractDict
• system/meshQualityDict 3. $> blockMesh
• system/blockMeshDict 4. $> snappyHexMesh –overwrite
• constant/triSurface/surfacemesh.stl 5. $> checkMesh –latestTime
• constant/triSurface/surfacemesh.eMesh 6. $> paraFoam
• The file surfacemesh.eMesh is generated after using the utility surfaceFeatureExtract, • In step 2 we extract the sharp angles from the geometry.
which reads the dictionary surfaceFeatureExtractDict.
• The utility surfaceFeatureExtract, will save a set of *.obj files with the captured edges. • In step 3 we generate the background mesh.
These files are located in the directory constant/extendedFeatureEdgeMesh. You can • In step 4 we generate the body fitted mesh. Have in mind that as we use the
use paraview to visualize the *.obj files.
option –overwrite, we are not saving the intermediate steps.
• In step 5 we check the mesh quality.
474 475
$PTOFC/101SHM/M1_cyl/C2
addLayersControls
{
//Global parameters
relativeSizes true;
castellatedMesh true; //or false expansionRatio 1.2;
finalLayerThickness 0.5;
Set this parameter to snap true; //or false minThickness 0.1;
true if you want to
enable boundary layer
addLayers true; //or false layers
meshing { Name of the surface or user-defined
banana_stlSurface patch where you want to add the
... {
nSurfaceLayers 3;
boundary layer mesh.
... }
}
...
// Advanced settings
...
...
...
478 479
addLayersControls
{
...
...
...
// Advanced settings
nGrow 0;
featureAngle 130; Increase this value to avoid BL relativeSizes true relativeSizes false
collapsing expansionRatio 1.2 expansionRatio 1.2
finalLayerThickness 0.5 firstLayerThickness 0.025
... minThickness 0.1 minThickness 0.01
... featureAngle 130 featureAngle 130
... nSurfaceLayers 3 nSurfaceLayers 3
Surface based refinement level (2 4) Surface based refinement level (2 4)
}
480 481
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
• When the option relativeSizes is true, the boundary layer meshing is done relative to the size
of the cells next to the surface.
• This option requires less user intervention but can not guarantee a uniform boundary layer.
• When the option relativeSizes is false, we give the actual thickness of the layers.
• Also, it is quite difficult to set a desired thickness of the first layer.
• This option requires a lot user intervention but it guarantees a uniform boundary layer and the
482 desired layer thickness. 483
Effect of different parameters on the boundary layer meshing Effect of different parameters on the boundary layer meshing
• When the option relativeSizes is true and in order to have a uniform boundary layer, we need
to have a uniform surface refinement. • To avoid boundary layer collapsing close to the corners, we can increase the value of the
boundary layer parameter featureAngle.
• Nevertheless, we still do not have control on the desired thickness of the first layer. 484 485
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 • To generate the mesh, in the terminal window type:
1. $> foamCleanTutorials
2. $> surfaceFeatureExtract
3. $> blockMesh
4. $> snappyHexMesh -overwrite
5. $> checkMesh –latestTime
6. $> paraFoam
relativeSizes false relativeSizes false
nSurfaceLayers 6 nSurfaceLayers 6
Refinement region at the stl surface:
mode distance;
levels ((0.05 4))
• The disadvantage of setting relativeSizes to false, is that it is difficult to control the expansion
ratio from the boundary layer meshing to the far mesh.
• To control this transition, we can add a refinement region at the surface with distance mode.
486 487
• At the end of the meshing process you will get the following information • If you want to visualize the boundary layer thickness, you can enable
regarding the boundary layer meshing: writeFlags in the snappyhexMeshDict dictionary,
...
patch faces layers overall thickness ...
...
[m] [%]
...
• This is a general summary of the boundary layer meshing. ...
...
• Pay particular attention to the overall and thickness information.
• Overall is roughly speaking the thickness of the whole boundary layer.
• Thickness is the percentage of the patch that has been covered with the boundary layer mesh. A thickness of
100% means that the whole patch has been covered (a perfect BL mesh). 488 489
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
3D Cylinder with edge refinement and boundary layer. 3D Cylinder with edge refinement and boundary layer.
• Then you can use paraview/paraFoam to visualize the boundary layer • After creating the mesh and if you do not like the inflation layer or you want to
coverage. try different layer parameters, you do not need to start the meshing process
from scratch.
• To restart the meshing process from a saved state you need to save the
intermediate steps (castellation and snapping), and then create the inflation
layers starting from the snapped mesh.
• That is, do not use the option snappyHeshMesh -overwrite.
Boundary layer thickness and number of layers
• Also, in the dictionary controlDict remember to set the entry startFrom
to latestTime or the time directory where the snapped mesh is saved (in
this case 2).
• Before restarting the meshing, you will need to turn off the castellation and
snapping options and turn on the boundary layer options in the
snappyHexMeshDict dictionary.
• At this point, you can restart the meshing process by typing in the terminal,
• $> snappyHexMesh
• From this point on, please follow me.
• By the way, you can restart the boundary layer mesh from a previous mesh • We are all going to work at the same pace.
with a boundary layer. • Remember, $PTOFC is pointing to the path where you
• So in theory, you an add one layer at a time, this will give you more control unpacked the tutorials.
but it will require more manual work and some scripting.
492 493
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.
STL visualization with a single surface using paraview (the STL visualization with multiple surfaces using paraview (each
single surface in represented with a single color) color corresponds to a different surface)
• When you use a STL with multiple surfaces, you have more control over the meshing process.
• By default, STL files are made up of one single surface.
• If you want to create the multiple surfaces you will need to do it in the solid modeler.
• Alternatively, you can split the STL manually or using the utility surfaceAutoPatch. • When you use a STL with multiple surfaces, you have more control over the meshing process.
• Loading multiple STLs is equivalent to using a STL with multiple surfaces. • In this case, we were able to use different refinement parameters in the lateral and central
494
surface patches of the cylinder. 495
//Global parameters
relativeSizes true;
1. $> cd geo
expansionRatio 1.2;
Global BL parameters
finalLayerThickness 0.5; 2. $> surfaceAutoPatch geo.stl output.stl 130
minThickness 0.1;
layers
{ 3. $> cp output.stl ../constant/triSurface/surfacemesh.stl
“surface.*” POSIX wildcards are permitted
{ 4. $> cd ..
nSurfaceLayers 5;
}
surface0 Local surface patch 5. $> paraview
{
nSurfaceLayers 3;
expansionRatio 1.0;
Local BL parameters
• The utility surfaceAutoPatch will read the original STL file (geo.stl), and it will find the
finalLayerThickness 0.25;
minThickness 0.1; patches using an angle criterion of 130 (similar to the angle criterion used with the utility
}
}
surfaceFeatureExtract). It writes the new STL geometry in the file output.stl.
//Advanced settings • By the way, it is better to create the STL file with multiple surfaces directly in the solid modeler.
...
... • FYI, there is an equivalent utility for meshes, autoPatch. So if you forgot to define the
...
} 500
patches, this utility will automatically find the patches according to an angle criterion. 501
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.
• If you open the file output.stl, you will notice that there are three • The new STL file is already in the constant/triSurface directory.
surfaces defined in the STL file. The different surfaces are defined in by the • To generate the mesh, in the terminal window type:
following sections:
1. $> foamCleanTutorials
solid patch0
… Surface patch 1 • The name of the solid sections are 2. $> surfaceFeatureExtract
automatically given by the utility
endsolid patch0 3. $> blockMesh
surfaceAutoPatch.
4. $> snappyHexMesh -overwrite
solid patch1
• The convention is as follows: patch0, 5. $> checkMesh –latestTime
… Surface patch 2
patch1, pathc2, … patchN.
endsolid patch1
• If you do not like the names, you can • To visualize the mesh, in the terminal window type:
solid patch2
change them directly in the STL file.
… Surface patch 3 6. $> paraFoam
endsolid patch2
502 503
• This case is ready to run using the solver simpleFoam. But before running, • This case is ready to run with simpleFoam.
you will need to set the boundary and initial conditions. • If you are in a hurry and you do not want to create/edit the files 0/U, 0/p,
• You will need to manually modify the file constant/polyMesh/boundary constant/polyMesh/boundary, follow these steeps to run the case:
• Remember:
1. $> cp 0_org/* 0
• Base type boundary conditions are defined in the file boundary located
in the directory constant/polyMesh. 2. $> cp system/boundary_org constant/polyMesh/boundary
• Primitive or numerical type boundary conditions are defined in the field 3. $> renumberMesh –overwrite
variables files located in the directory 0 or the time directory from which 4. $> simpleFoam > log | tail –f log
you want to start the simulation (e.g. U, p).
• The name of the base type boundary conditions and numerical type
boundary conditions needs to be the same.
• Also, the base type boundary condition needs to be compatible with the
numerical type boundary condition.
504 505
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
2D Cylinder
• Meshing with snappyHexMesh.
• Meshing case 4. 2D Cylinder (external mesh).
$PTOFC/101SHM/M1_cyl/C4
From 3D To 2D
• From this point on, please follow me. • To generate a 2D mesh using snappyHexMesh, we need to start from a 3D. After all,
snappyHexMesh is a 3D mesher.
• We are all going to work at the same pace.
• To generate a 2D mesh (and after generating the 3D mesh), we use the utility
• Remember, $PTOFC is pointing to the path where you extrudeMesh.
unpacked the tutorials. • The utility extrudeMesh works by projecting a face into a mirror face. Therefore,
506
the faces need to parallel. 507
Geometry width
• How do we create the 2D mesh?
FACE 1
• After generating the 3D mesh, we use the utility extrudeMesh.
The utility extrudeMesh works by
projecting FACE 1 into FACE 2.
• This utility reads the extrudeMeshDict,
Therefore, the faces need to be
parallel.
constructFrom patch;
FACE 2 Background mesh width
sourceCase “.”
sourcePatches (minZ); Name of source patch
mergeFaces false;
508 509
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
2D Cylinder
• To generate the mesh, in the terminal window type: • Meshing with snappyHexMesh.
1. $> foamCleanTutorials • Meshing case 5. Mixing elbow (internal mesh)
2. $> blockMesh
3. $> snappyHexMesh –overwrite
$PTOFC/101SHM/M2_mixing_elbow
4. $> extrudeMesh
5. $> checkMesh –latestTime
6. $> paraFoam
• From this point on, please follow me.
• Remember, the utility extrudeMesh (step 4) reads the dictionary
• We are all going to work at the same pace.
extrudeMeshDict, which is located in the directory system.
• Also remember to set the empty patches in the dictionary boundary and in the
• Remember, $PTOFC is pointing to the path where you
boundary conditions. unpacked the tutorials.
510 511
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.
518 519
• 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
520 521
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
Mixing elbow.
• To solve the problem of the single surface patch, you can use the utility autoPatch.
To do so, you can proceed as follows:
• $> autoPatch 60 -overwrite
• Meshing with snappyHexMesh.
• The option -overwrite, will copy the new mesh in the directory • Meshing case 6. Ahmed body (external mesh)
constant/polyMesh.
• The utility autoPatch will use an angle criterion to find the patches, and will assign
the name auto0, auto1, auto2 and auto3 to the new patches. $PTOFC/101SHM/M3_CSTR
• The angle criterion is similar to that of the utility surfaceFeatureExtract.
• The only difference is that it uses the complement of the angle. So, the smaller the
angle the more patches it will find.
• The naming convention is autoN, where N is the patch number. • From this point on, please follow me.
• Remember, autoPatch will manipulate the mesh located in the directory • We are all going to work at the same pace.
constant/polyMesh. • Remember, $PTOFC is pointing to the path where you
• FYI, autoPatch does not un in parallel. unpacked the tutorials.
522 523
Impeller
http://www.wolfdynamics.com/training/meshing/image5.gif
• In this case we are going to use multiple STL and eMesh files. • We are going to work with sliding grids (the impeller will be rotating), therefore we
• Each color in the figure above represents a different STL. need to divide the mesh in two regions, one fix region and one rotating region.
• Working with multiple STL is no different from working with a single STL, we just need • To split the mesh in two regions we are going to use another STL file (the green
to read all the STLs. surface), plus a few utilities to manipulate the mesh.
• When working with multiple STL we have more control on the local refinement. • We will show how to setup conforming patches between regions.
524 525
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
• In this case we are going to generate a body fitted mesh with two regions and using multiple • At this point, we are going to work in parallel.
STL files.
• To generate the mesh, in the terminal window type:
• For simulation purposes, one of the regions will be in motion.
• This is an internal mesh.
• These are the dictionaries and files that will be used. 1. $> foamCleanTutorials
• system/snappyHexMeshDict 2. $> foamCleanPolymesh
• system/meshQualityDict
• system/surfaceFeatureExtractDict 3. $> surfaceFeatureExtract
• system/decomposeParDict
4. $> blockMesh
• system/blockMeshDict
• constant/triSurface/impeller.stl 5. $> decomposePar
• constant/triSurface/impeller.eMesh
• constant/triSurface/inner_volume.stl 6. $> mpirun -np 4 snappyHexMesh –parallel –overwrite
• constant/triSurface/inner_volume.eMesh $> mpirun -np 4 checkMesh –parallel –latestTime
7.
• constant/triSurface/shaft.stl
• constant/triSurface/shaft.eMesh 8. $> reconstructParMesh -constant
• constant/triSurface/sparger.stl
• constant/triSurface/sparger.eMesh 9. $> paraFoam
• constant/triSurface/vesel.stl
• constant/triSurface/vesel.eMesh
526 527
• Let us take a look at the dictionary surfaceFeatureExtractDict. • Let us take a look at the geometry section of the dictionary snappyHexMeshDict.
• Notice that we are reading multiple STL files.
• Notice that we are reading multiple STL files.
geometry
{
vessel.stl STL file to read.
vessel.stl Name of the STL. {
{ type triSurfaceMesh;
… Edge detection parameters. name vessel; Name of the surface inside snappyHexMesh.
}
Use regions if you have a STL regions
sparger.stl
with multiple patches defined.
{ {
This is the name of the region or surface
… inlet
patch in the STL file .
} User-defined patch name. {
shaft.stl Note: This is the final name of the name inlet;
{ patch. }
… An individual eMesh file will be generated outlet
} for each individual STL. That is: {
inner_volume.stl name outlet;
{ }
… vessel.stl → vessel.eMesh }
} sparger.stl → sparger.eMesh }
impeller.stl inner_volume.stl Define every single STL that
shaft.stl → shaft.eMesh you want to use.
{ Inner_volume.stl → inner_volume.eMesh {
… type triSurfaceMesh;
}
impeller.stl → impeller.eMesh name inner_volume;
}
…
…
…
}
528 529
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 • Let us take a look at the castellatedMeshControls section of the dictionary
snappyHexMeshDict. snappyHexMeshDict.
• Notice that we are reading multiple eMesh files. • In this block we define the cellZone and faceZone, as follows,
castellatedMeshControls
{
... castellatedMeshControls
... {
... ...
...
//Explicit feature edge refinement ...
features
( //Surface based refinement Using the surface inner_volume we create a
{ inner_volume mesh zone that we will use at a later time to
Define every single eMesh file that (
file ”vessel.eMesh"; split the whole mesh in two regions.
level 0; you want to use. level (1 1);
}
{
Define every single eMesh file that
cellZone cell_inner_volume; Name of the cellZone.
file ”shaft.eMesh";
you want to use.
level 0; faceZone face_inner_volume; Name of the faceZone.
}
... cellZoneInside insidePoint; Use an inner point to define location of the zone
...
... insidePoint (50 0 100); Location of the insidePoint.
); The point is located inside the surface
); ...
inner_volume, therefore the new zone is
} ...
... created inside the surface selected.
}
530 531
• Using paraFoam let’s take a look at the newly created zone. • To visualize the zones in paraFoam you will need to enable the option
Include Zones
• Then select the mesh parts cell_inner_volume and face_inner_volume.
face_inner_volume cell_inner_volume
1. 2.
532 533
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 • So far we only generated the mesh.
information: • The next step will consist in splitting the mesh in two regions.
• $> checkMesh
• Let us now create the two regions.
… • We will use the following dictionaries and files:
…
…
• The utility createBaffles, reads the dictionary createBafflesDict. • To create the two regions we proceed as follows (notice that we are going to
• With this utility we create the interface patches between the fix zone and the work in serial from now on)
rotating zone.
Boundary condition
{
name AMI1; Name of the master patch (user defined) 5. $> splitMeshRegions –detectOnly
type cyclicAMI;
for sliding grids matchTolerance 0.0001;
neighbourPatch AMI2;
transform noOrdering;
Neighbour patch (slave patch or AMI2) 6. $> transformPoints –scale ‘(0.01 0.01 0.01)’
}
slave Parameters for the slave patch
{
Boundary condition name AMI2; Name of the slave patch (user defined)
type cyclicAMI;
for sliding grids matchTolerance 0.0001;
neighbourPatch AMI1; Neighbour patch (master patch or AMI1)
transform noOrdering;
}
}
}
} The master and slave patches
share a common face 536 537
snappyHexMesh guided tutorials snappyHexMesh guided tutorials
CSTR – Continuous stirring tank reactor mesh CSTR – Continuous stirring tank reactor mesh
• So what did we do?
• At this point and if you run checkMesh, you will get the following information:
• Step 1:
• $> checkMesh
• Splits the mesh in regions using the baffles (faceZone), created during the meshing
stage. …
…
• We also create the cyclicAMI patches AMI1 and AMI2. …
Checking topology…
• At this point we have two regions and one zone. However, the two regions are stich Boundary definition OK.
together via the patches AMI1 and AMI2. Cell to face addressing OK.
Point usage OK.
• Step 2: topologically split the patches AMI1 and AMI2. As we removed the link between UPPER triangular ordering OK.
Face vertices OK.
AMI1 and AMI2, the regions are free to move. *Number of regions: 2
The mesh has multiple regions which are not connected by any face.
• Step 3 (optional): gets rid of zero faced patches if hey exist. These are the patches <<Writing region information to ”0/cellToRegion”
remaining from the base mesh, as they are empty, we do not need them. <<Writing region 0 with 136187 cells to cellSet region0
<<Writing region 1 with 67682 cells to cellSet region1
• Step 4 (optional): …
…
• Splits mesh into multiple zones. It will create automatically the sets and zones. …
• At this point we have two regions and two zones.
• Step 5 (optional): just to show the regions and names. • As you can see, we now have two regions.
• Step 6 (optional): scales the mesh. • At this point the mesh is ready to use.
538 • You can visualize the mesh (with all the sets and zones) using paraFoam. 539
$PTOFC/101SHM/M4_ahmed
544 545
Mesh conversion Mesh conversion
• Let us visit the mesh directory. In the terminal type: • In the directory $FOAM_UTILITIES/mesh/conversion you will find the following
• $> util mesh conversion utilities:
• $> cd mesh
• ansysToFoam • kivaToFoam
• $> ls –al
• cfx4ToFoam • mshToFoam
• datToFoam • netgenNeutralToFoam
• In this directory you will find the directories containing the source code for the • fluent3DMeshToFoam • Optional/ccm26ToFoam
following mesh utilities
• fluentMeshToFoam • plot3dToFoam
• advanced
• foamMeshToFluent • sammToFoam
• conversion
• foamToStarMesh • star3ToFoam
• generation
• foamToSurface • star4ToFoam
• Manipulation
• gambitToFoam • tetgenToFoam
• gmshToFoam • vtkUnstructuredToFoam
• In the directory conversion you will find the source code for the mesh conversion
• ideasUnvToFoam • writeMeshObj
utilities. Let us visit this directory, in the terminal type:
• $> cd conversion
• $> ls -al
546 547
Processing tag:2412
• Remember to always check the file boundary after converting the mesh.
inlet1 358
inlet2 78 Boundary patches detected
outlet 358
End
550 551
552 553
Mesh conversion Mesh conversion
Case 1. Mixing elbow (internal mesh). Case 1. Mixing elbow (internal mesh).
• The boundary file. • The boundary file.
554 555
2. $> checkMesh
3. $> paraFoam
1. Meshing preliminaries
2. What is a good mesh?
3. Mesh quality assessment in OpenFOAM® • First at all, by mesh manipulation we mean modifying a valid
4. Mesh generation using blockMesh. OpenFOAM® mesh.
5. blockMesh guided tutorials. • These modifications can be scaling, rotation, translation,
6. Mesh generation using snappyHexMesh. mirroring, topological changes, mesh refinement and so on.
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
• In the directory $FOAM_UTILITIES (use the alias util to go there) you will find the • Let us visit the mesh directory. In the terminal type:
following sub-directories containing the source code for the utilities available in the • $> util
OpenFOAM® installation (version 5.x):
• $> cd mesh
• mesh • $> ls –al
• miscellaneous
• parallelProcessing • In this directory you will find the directories containing the source code for the
following mesh utilities
• postProcessing
• advanced
• preProcessing
• conversion
• surface
• generation
• thermophysical
• manipulation
• In the sub-directory mesh you will find the source code for the mesh utilities in the
OpenFOAM® installation. • In the directory manipulation you will find the source code for the mesh
manipulation utilities. Let us visit this directory, in the terminal type:
• $> cd manipulation
• $> ls -l
560 561
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
• In the directory $FOAM_UTILITIES/mesh/manipulation you will find the • Inside each utility directory you will find a *.C file with the same name as
following mesh manipulation utilities: the directory. This is the main file, where you will find the top-level source
• attachMesh • orientFaceZone code and a short description of the utility.
• autoPatch • polyDualMesh • For instance, in the directory checkMesh, you will find the file
• checkMesh • refineMesh checkMesh.C, which is the source code of the utility checkMesh. In the
• createBaffles • renumberMesh source code you will find the following description:
• createPatch • rotateMesh
Checks validity of a mesh.
• deformedGeom • setSet
• flattenMesh • setsToZones Usage
• insideCells • singleCellMesh - checkMesh [OPTION]
562 Take your time and dig into each directory to get a complete description of each utility. 563
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
• In OpenFOAM® it is also possible to manipulate the geometries in STL format. • Let us visit the surface directory. In the terminal type:
• In the directory $FOAM_UTILITIES (use the alias util to go there) you will find the • $> util
sub-directories containing the source code for the utilities available in the • $> cd surface
OpenFOAM® installation (version 5.x):
• mesh • In this directory you will find the directories containing the source code for the surface
manipulation utilities.
• miscellaneous
• parallelProcessing
• postProcessing • Let us see what is inside this directory, in the terminal type:
• preProcessing • $> ls -al
• surface
• thermophysical
• In the sub-directory surface you will find the source code for the surface
manipulation utilities in the OpenFOAM® installation.
564 565
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
• In the directory $FOAM_UTILITIES/surface you will find the following surface • Inside each utility directory you will find a *.C file with the same name as
manipulation utility sub-directories: the directory. This is the main file, where you will find the top-level source
• surfaceAdd • surfaceMeshExport code and a short description of the utility.
• surfaceAutoPatch • surfaceMeshImport • For instance, in the directory surfaceTransformPoints, you will find the
• surfaceBooleanFeatures • surfaceMeshInfo file surfaceTransformPoints.C, which is the source code of the utility
• surfaceCheck • surfaceMeshTriangulate surfaceTransformPoints. In the source code you will find the following
• surfaceClean • surfaceOrient description:
• surfaceCoarsen • surfacePointMerge
• surfaceConvert • surfaceRedistributePar Transform (scale/rotate) a surface.
• surfaceFeatureConvert • surfaceRefineRedGreen Like transformPoints but for surfaces.
• surfaceFeatureExtract • surfaceSplitByPatch The rollPitchYaw option takes three angles (degrees):
• surfaceFind • surfaceSplitByTopology - roll (rotation about x) followed by
• surfaceHookUp • surfaceSplitNonManifolds - pitch (rotation about y) followed by
• surfaceInertia • surfaceSubset
- yaw (rotation about z)
• surfaceLambdaMuSmooth • surfaceToPatch
The yawPitchRoll does yaw followed by pitch followed by roll.
• surfaceMeshConvert • surfaceTransformPoints
• surfaceMeshConvertTesting
566 Take your time and dig into each directory to get a complete description of each utility. 567
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 located in 1. $> foamCleanTutorials
the directory: 2. $> surfaceMeshInfo ./constant/triSurface/ahmed_body.stl
3. $> surfaceCheck ./constant/triSurface/ahmed_body.stl
$> surfaceTransformPoints -rollPitchYaw '(0 0 15)’
$PTOFC/mesh_quality_manipulation/M5_ahmed_body_transform 4. ./constant/triSurface/ahmed_body.stl rotated.stl
$> surfaceTransformPoints -translate '(0 0.12 0)'
5. ./constant/triSurface/ahmed_body.stl translated.stl
$> surfaceTransformPoints -scale '(0.9 1.1 1.3)'
6. ./constant/triSurface/ahmed_body.stl scaled.stl
$> surfaceInertia -density 2700 –noFunctionObjects
• From this point on, please follow me. 7. ./constant/triSurface/ahmed_body.stl
• We are all going to work at the same pace. 8.
$> surfaceOrient ./constant/triSurface/ahmed_body_wrong_normals.stl
out.stl ‘(1e10 1e10 1e10)’
• Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
568 569
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.
570 571
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 • We will now do some mesh manipulation.
Select the Normal Glyphs from the filter menu
$PTOFC/mesh_quality_manipulation/M7_cylinder_transform
7. $> checkMesh
8. $> paraFoam
574 575
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Mesh manipulation in OpenFOAM® Mesh manipulation in OpenFOAM®
After renaming the patches and transforming the mesh, we can use it to conduct this buoyant flow
simulation
www.wolfdynamics.com/wiki/heated_cyl/ani1.gif
576 577
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Mirroring a mesh in OpenFOAM®
• Let us mirror a mesh.
• For this we will use the wing body tutorial located in
the directory:
$PTOFC/mesh_quality_manipulation/M1_wingbody
Geometry and mesh manipulation utilities Geometry and mesh manipulation utilities
Mirroring a mesh in OpenFOAM® Mirroring a mesh in OpenFOAM®
• We will mirror a mesh. In the terminal type: • Step 4, will create the cellSet that we will use with subsetMesh. It reads the
dictionary system/topoSetDict
• In step 5, we use the set newcells created with topoSet to create a new polyMesh.
1. $> foamCleanTutorials The new polyMesh will not contain the unusedPoints.
2. $> fluent3DMeshToFoam ../../meshes_and_geometries/fluent_wingbody/ascii.msh • It steps 4 and 5 we simply removed faulty sets.
3. $> checkMesh • In step 6, we mirror the mesh after removing some faulty sets. The utility
$> topoSet –dict system/topoSetDict1 mirrorMesh will read the dictionary mirrorMeshDict located in the directory
4.
system. In this dictionary we define the base point for the mirror plane and the
5. $> subsetMesh newcells -overwrite vector normal to the mirror plane.
6. $> mirrorMesh –noFunctionObjects
7. $> checkMesh
8. $> paraFoam
580 581
Roadmap
Module 4
1. Running in parallel - Running in a cluster
Running in parallel using a job scheduler
582 583
Shared memory architectures – Workstations and portable computers • We have been able to run in parallel up to 14000 processors.
• We have been able to run OpenFOAM® using single GPU and multiple
GPUs.
• Do not ask about scalability, that is problem/hardware specific.
• If you want to learn more about MPI and GPU programming, do not look
in my direction.
Distributed memory architectures – Clusters and super computers • And of course, to run in parallel you need the hardware.
588 589
Running in parallel Running in parallel
To run OpenFOAM® in parallel you will need to: Domain Decomposition in OpenFOAM®
• The mesh and fields are decomposed using the decomposePar utility.
• Decompose the domain. • They are broken up according to a set of parameters specified in a dictionary named
decomposeParDict that is located in the system directory of the case.
To do so we use the decomposePar utility. You also need the dictionary
decomposeParDict which is located in the system directory. • In the decomposeParDict dictionary the user must set the number of domains in
which the case should be decomposed (using the keyword numberOfSubdomains).
The value used should correspond to the number of physical cores available.
• Distribute the jobs among the processors or computing nodes.
To do so, OpenFOAM® uses the standard message passing interface (MPI).
By using MPI, each processor runs a copy of the solver on a separate part numberOfSubdomains 128; Number of subdomains
of the decomposed domain. method scotch; Decomposition method
• 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).
594 595
• 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
596 You will find this case in the directory: $PTOFC/parallel/kelvin_helmholtz 597
Running in parallel Running in parallel
Comparison of the Kelvin Helmholtz instability in a coarse and fine mesh Visualization of a parallel case
• The traditional way is to first reconstruct the case and then do the post-
processing and visualization on the reconstructed case.
1. $> reconstructPar
2. $> paraFoam
• Step 1 reconstruct the case. Remember, you can choose to reconstruct all
the time steps, the last time step or a range of time steps.
Cells 200 X 40 X 1 Cells 3200 X 640 X 1 • In step 2, we use paraFoam to visualize the reconstructed case.
598 599
• An alternative way to visualize the solution, is by proceeding in the following • Both of the previous methods are valid.
way • When we use the option –builtin with paraFoam, we have the option to
• $> paraFoam –builtin work on the decomposed case directly.
• That is to say, we do not need to reconstruct the case.
• The option –builtin let us post-process the decomposed case directly. • But wait, there is a third option.
• Remember, you will need to select on the object inspector the Decomposed • The third option consist in post-processing each decomposed domain
Case option. individually.
• To load all processor directories, you will need to manually create the file
processorN.OpenFOAM (where N is the processor number) in each
processor folder.
• After creating all processorN.OpenFOAM files, you can launch paraFoam
and load each file (the processorN.OpenFOAM files).
• As you can see, this option requires more input from the user.
600 601
Running in parallel Running in parallel
Decomposing big meshes Do all utilities run in parallel?
• One final word, the utility decomposePar does not run in parallel. So, it is • At this point, you might be wondering if all solvers/utilities run in parallel.
not possible to distribute the mesh among different computing nodes to do
• To know what solvers/utilities do not run in parallel, in the terminal type:
the partitioning in parallel.
• $> find $WM_PROJECT_DIR -type f | xargs grep –sl ‘noParallel’
• Paradoxically, the utilities used to decompose the domain and reconstruct the
• If you need to partition big meshes, you will need a computing node with domain do not run in parallel.
enough memory to handle the mesh. We have been able to decompose
• Another important utility that does not run in parallel is blockMesh. So to generate
meshes with up to 500.000.000 elements, but we used a computing node big meshes with blockMesh you need to use a big fat computing node.
with 512 gigs of memory.
• 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
• For example, in a computing node with 16 gigs of memory, it is not possible directory $WM_THIRD_PARTY_DIR), set the option withMPI to true,
to decompose a mesh with 30.000.000. You will need to use a computing • withMPI = true
node with at least 32 gigs of memory.
• While you are working with the file makeParaView4, you might consider enabling
Python support,
• Same applies for the utility reconstructPar. • withPYTHON = true
602 603
• BlueGene LoadLeveler (LL). mpirun –np 128 pimpleFoam -parallel > log //run parallel solver
• Ask your system administrator the job scheduler installed in your system.
Hereafter we will assume that you are using PBS. The green lines are not PBS comments, they are comments inserted in this slide. PBS comments use the number
sign (#).
604 605
Running in parallel Running in parallel
• To launch your job you need to use the qsub command (part of the PBS job • Finally, remember to always plan how you will use the resources available.
scheduler). The command qsub will send your job to queue. • For example, if each computing node has 8 gigs of memory available and 8 cores.
You will need to distribute the work load in order not to exceed the maximum
resources available per computing node.
• $> qsub script_name
• So if you are running a simulation that requires 32 gigs of memory, the following
options are valid:
• Remember, running in a cluster is no different from running in your
• Use 4 computing nodes and ask for 32 cores. Each node will use 8 gigs of
workstation or portable computer. The only difference is that you need to
memory and 8 cores.
schedule your jobs.
• Use 8 computing nodes and ask for 32 cores. Each node will use 4 gigs of
memory and 4 cores.
• Depending on the system current demand of resources, the resources you • Use 8 computing nodes and ask for 64 cores. Each node will use 4 gigs of
request and your job priority, sometimes you can be in queue for hours, even memory and 8 cores.
days, so be patient and wait for your turn. • But the following options are not valid:
• Use 2 computing nodes. Each node will need 16 gigs of memory.
• Remember to always double check your scripts. • Use 16 computing nodes and ask for 256 cores. The maximum number of cores
for this job is 128.
606 607
Roadmap
608 609
Sampling with the postProcess utility Sampling with the postProcess utility
• OpenFOAM® provides the postProcess utility to sample field data for
plotting.
• The sampling locations are specified in the a dictionary located in the case
• Let us do some sampling.
system directory. You can give any name to the input dictionary, hereafter • For this we will use the 3D pipe case, which you will
we are going to name it sampleDict.
find in the directory:
• During the sampling, inside the case directory a new directory named
postProcessing, will be created. In this directory, the sampled values are
stored. $PTOFC/postprocessing/pipe/
• This utility can sample points, lines, and surfaces.
• Data can be written in a range of formats including well-known plotting
packages such as: grace/xmgr, gnuplot and jPlot.
• The sampling can be executed by running the utility postProcess in the • From this point on, please follow me.
case directory and according to the application syntax. • We are all going to work at the same pace.
• A final word, this utility does not do the sampling while the solver is running. • Remember, $PTOFC is pointing to the path where you
It does the sampling after you finish the simulation. unpacked the tutorials.
610 611
Sampling with the postProcess utility Sampling with the postProcess utility
Laminar flow in a straight pipe – Re = 600 Laminar flow in a straight pipe – Re = 600
614 615
Sampling with the postProcess utility Sampling with the postProcess utility
Laminar flow in a straight pipe – Re = 600 What are we going to do?
616 617
Sampling with the postProcess utility Sampling with the postProcess utility
Running the case Running the case
• Let us run the simulation and do some sampling. In the terminal type: • In step 4 we use the utility topoSet to do mesh topological manipulation.
This utility will read the dictionary topoSetDict located in the system
$> foamCleanTutorials
directory. Later on, we will talk about what are we doing in this step.
1.
$> blockMesh
• In step 5 we run the simulation and save the log file.
2.
$> checkMesh
• In step 6 we use the postProcess utility. By using the option –func we
3.
specify to do the sampling according to the dictionary
4. $> topoSet system/sampleDict1. We sample the latest saved solution.
5. $> pisoFoam | tee log • In step 7 we use the postProcess utility. By using the option –func we
6. $> postProcess -func sampleDict1 -latestTime specify to do the sampling according to the read dictionary
7. $> postProcess -func sampleDict2 -latestTime system/sampleDict2. We sample the latest saved solution.
8. $> gnuplot gnuplot/gnuplot_script • In step 8 we use the gnuplot script gnuplot/gnuplot_script to plot the
sampled fields. Feel free to take a look at the script and to reuse it.
9. $> paraFoam
• Finally, in step 9 we visualize the solution.
• Do not erase the solution, we are going to use it in the next sections.
618 619
Sampling with the postProcess utility Sampling with the postProcess utility
The sampleDict dictionary The sampleDict1 dictionary
Sample sets (points and lines).
• Let us visit the sampleDict dictionaries. Format of the output file, raw format is a generic format that can be
read by many applications. The file is human readable (ascii
• This dictionary is located in the directory system. 17
18
type sets;
format).
19 setFormat raw;
29
622 623
Sampling with the postProcess utility Sampling with the postProcess utility
The sampleDict2 dictionary The output files
53
Name of the output file
54
55
surf3
{ • The output format of the point sampling (cloud) is as follows:
56 type sampledTriSurfaceMesh; Surface sampling method. In this case we are using a STL
57 surface surface2.stl;
58 source cells; file, the file is always located in the directory
59
60 interpolate true;
constant/triSurface. Scalars
61 }
62
63 surf4 Name of the output file
64 { #POINT_COORDINATES (X Y Z) SCALAR_VALUE
65 type sampledTriSurfaceMesh; Surface sampling method. In this case we are using a STL
66 surface surface3.stl; 0 0 0.05 13.310995
file, the file is always located in the directory
67
68
source insideCells;
constant/triSurface. 0 0 0.1 19.293817
69 interpolate false; …
70 }
71 ); The sampled information is always saved in the directory
postProcessing/sampleDict2
As we are sampling the latest solution (0.1), the sampled data Vectors
will be located in the directory:
postProcessing/sampleDict2/0.1
#POINT_COORDINATES (X Y Z) VECTOR_COMPONENTS (X Y Z)
The files p_surf1.raw, p_surf2.raw, p_surf3.raw, 0 0 0.05 0 0 2.807395
p_surf4.raw, U_surf1.raw, U_surf2.raw, 0 0 0.1 0 0 2.826176
U_surf3.raw, and U_surf4.raw, located in the directory …
postProcessing/sampleDict2/0.1 contain the sampled
data. Feel free to open the output files using your favorite text
editor.
624 625
Sampling with the postProcess utility Sampling with the postProcess utility
The output files The output files
• The output format of the line sampling is as follows: • The output format of the surface sampling is as follows:
Scalars Scalars
Vectors Vectors
626 627
Sampling with the postProcess utility Sampling with the postProcess utility
• To plot the sampled data using gnuplot we can proceed as follows: • To plot the sampled data using gnuplot we can proceed as follows:
1. gnuplot> set title 'Radial velocity at z=0.2 - Time 0.1 s' 1. gnuplot> set title 'Velocity profile at plane located at z = 0.1 - Time 0.1 s'
628 629
Sampling with the postProcess utility Sampling with the postProcess utility
Creating faceSet and zoneSet The topoSetDict dictionary
faceZone/cellZone. 32
33
{
action new;
34 name internalfacepatch;
• In this step we convert the faceSet internalFaces, to a
• Creating an internal faceZone is particularly important if we are interested in 35
36
type faceZoneSet;
faceZone.
computing the mass flow in an internal surface, as sampledSurface does not work 37
38
source setToFaceZone;
sourceInfo
• The name of new faceZone is internalfacepatch.
• At this point, we can use this faceZone to do sampling.
with surfaceScalarFields, therefore we need to use a faceZone. Alternatively, we 39
40
{
faceSet internalfaces; • We can visualize this zone in paraFoam.
can compute the mass flow in paraFoam/paraView or we can use the
41 }
42 }
43
areaNormaIntegrate operation on the sampleSurface.
• Let us create an internal faceZone and a cellZone and let us compute the mass flow
and do some sampling on these sets.
Note:
Use the banana method to know all the options
available.
630 631
Sampling with the postProcess utility Sampling with the postProcess utility
The topoSetDict dictionary • Let us create an internal faceZone and a cellZone and let us compute the mass flow
and do some sampling on these sets.
44 {
45 action new; • In this step we are creating a new cellSet from a boxToCell
46 name internalcells; source.
47
48
type cellSet;
• The name of the new cellSet is internalCells. 1. $> topoSet
49 source boxToCell; • The box source encloses the cells we want to tag.
50
51
sourceInfo
{
• We can visualize this set in paraFoam. 2. $> pisoFoam -postProcess -dict system/functionobject3 –latestTime
52 box (-1 -1 0.096) (1 1 0.1); • Remember, we can not sample on a cellSet, we need to
53
54 }
} convert it to a cellZone. 3. $> pisoFoam -postProcess -dict system/functionobject4 -latestTime
55
56 {
57 action new;
58 name internalcells;
59 type cellZoneSet;
60 • In this step we convert the cellSet internalcells, to a cellZone.
61
62
source setToCellZone;
sourceInfo • The name of new cellZone is internalcells. • In step 1 we use the utility topoSet to create the new faceZone and cellZone.
63 { • At this point, we can use this cellZone to do sampling.
64
65 }
set internalcells;
• We can visualize this set in paraFoam. • In step 2 we run a functionObject a-posteriori. In this functionObject we compute:
66 }
67
68 );
• Mass flow in a sampledSurface.
• Mass flow in a faceZone.
• In step 3 we run a functionObject a-posteriori. In this functionObject we compute:
• Volume integral in a cellZone.
Note:
Use the banana method to know all the options
available.
632 633
Sampling with the postProcess utility Sampling with the postProcess utility
Visualizing the newly created sets and zones The functionobject3 dictionary
17 functions
18 {
19
21 surface1_massflow
22 {
23 type surfaceRegion;
24 functionObjectLibs ("libfieldFunctionObjects.so");
25 enabled true;
26
27 writeControl timeStep;
28 writeInterval 1;
Check the option Include Sets cellZone - In white 29
to visualize the sets 30 log true;
31 writeFields false;
32
33 regionType sampledSurface;
34 Name dummy;
35
36 sampledSurfaceDict
37 {
38 type sampledTriSurfaceMesh;
39 surface surface1.stl;
Check the option Include Zones 40 source cells;
41 interpolate false;
to visualize the zones 42 }
43
54
55
operation
fields
areaNormalIntegrate;
• Compute mass flow using areaNormalIntegrate
faceZone - In red 56 ( operation with the field U.
57 U
58
59
);
• Using the operation sum with the field phi, will not
60 } work because phi is a surfaceScalarField.
Sampling with the postProcess utility Sampling with the postProcess utility
The functionobject3 dictionary The functionobject3 dictionary
64 surface2_massflow
65 {
66 type surfaceRegion;
67 functionObjectLibs ("libfieldFunctionObjects.so"); 90 surface3_massflow
68 enabled true; 91 {
69 92 type surfaceRegion;
70 writeControl timeStep; 93 functionObjectLibs ("libfieldFunctionObjects.so");
71 writeInterval 1; 94 enabled true;
72 95
73 log true; 96 writeControl timeStep;
74 writeFields false; 97 writeInterval 1;
75 98
76 regionType faceZone; 99 log true;
77 name internalfacepatch; 100 writeFields false;
78 101
79 operation sum; 102 regionType sampledSurface;
80 fields 103 name dummy;
81 ( 104
82 phi 105 sampledSurfaceDict
83 ); 106 {
84 107 type sampledTriSurfaceMesh;
85 } 108 surface surface2.stl;
109 source cells;
In this case we are using a finer surface therefore we
• Compute mass flow using sum operation with the 110 interpolate true;
111 } enable the option interpolate.
field phi. 112
113 operation areaNormalIntegrate;
• In this case it works because we are sampling on 114 fields
a faceZone.
115
116
(
U
Compute mass flow using areaNormalIntegrate
117 ); operation with the field U.
• The faceZone are internal faces of the mesh. 118
119 }
636 637
Sampling with the postProcess utility Sampling with the postProcess utility
The functionobject3 dictionary The functionobject3 dictionary
123 surface4_massflow 156 plane1_massflow
124 { 157 {
125 type surfaceRegion; 158 type surfaceRegion;
126 functionObjectLibs ("libfieldFunctionObjects.so"); 159 functionObjectLibs ("libfieldFunctionObjects.so");
127 enabled true; 160 enabled true;
128 161
129 writeControl timeStep; 163 writeControl timeStep;
130 writeInterval 1; 164 writeInterval 1;
131 165
132 log true; 166 log true;
133 writeFields false; 167 writeFields false;
134 168
135 regionType sampledSurface; 169 regionType sampledSurface;
136 name dummy; 170 name dummy;
137 171
138 sampledSurfaceDict 172 sampledSurfaceDict
139 { 173 {
140 type sampledTriSurfaceMesh; 174 type plane;
141 surface surface3.stl; 175 normalVector (0 0 1); We sample in a plane.
142 source insideCells; 176 basePoint (0 0 0.1);
143 interpolate true; 177 }
144 } 178
145 180 operation areaNormalIntegrate;
146 operation areaNormalIntegrate; 181 fields
147 fields 182 (
148 ( 183 //phi
149 U Compute mass flow using areaNormalIntegrate 184 U Compute mass flow using areaNormalIntegrate
150
151
);
operation with the field U. 185
186 }
);
operation with the field U.
152 } 188
189 }
638 639
640 641
Probing with the postProcess utility Probing with the postProcess utility
• OpenFOAM® provides the postProcess utility to probe field data for Laminar flow in a straight pipe – Re = 600
plotting.
• The probing locations are specified in the a dictionary located in the case
system directory. You can give any name to the input dictionary, hereafter
we are going to name it probesDict.
• During the probing, inside the case directory a new directory named
postProcessing, will be created. In this directory, the sampled values are
stored.
• This utility can sample only points.
• Data can be written in a range of formats including well-known plotting
packages such as: grace/xmgr, gnuplot and jPlot.
• The probing can be executed by running the utility postProcess in the
case directory and according to the application syntax.
• A final word, this utility does not do the sampling while the solver is running.
It does the sampling after you finish the simulation. Probes location
642 643
Probing with the postProcess utility Probing with the postProcess utility
• We hope you did not erase the previous solution because we will use it to play The probesDict dictionary
around with the probeLocations. In the terminal type:
17 type probes;
• As we started to sample from time 0, the sample data is saved in the directory
• postProcessing/probesDict/0
• The output format of the probing is as follows: • The output format of the probing is as follows:
Scalars Vectors
646 647
648 649
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
$PTOFC/postprocessing/pipe
650 651
• We will use this case to introduce functionObjects. • Let us run the simulation. In the terminal type:
• We will use the utility postProcess, to run functionObjects a-posteriori.
• We will also use the utility postProcess, to compute some quantities in patches.
1. $> foamCleanTutorials
• We will compare the numerical solution with the analytical solution.
2. $> blockMesh
• We will do data cleaning and data analytics using shell scripting. $> checkMesh
3.
• To find the numerical solution we will use the solver pisoFoam. $> topoSet
4.
• After finding the numerical solution we will do some sampling. 5. $> pisoFoam > log &
• At the end, we will do some plotting (using gnuplot or Python) and scientific 6. $> pyFoamPlotWatcher.py log
visualization.
7. $> paraFoam
652 653
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
Running the case • Let us explore the case directory.
• You will notice that we now have a new directory named postProcessing.
• In step 4 we use the utility topoSet to do mesh topological manipulation.
This utility will read the dictionary topoSetDict located in the system • Inside this directory, you will find many subdirectories pointing to the
directory. Later on, we will talk about what are we doing in this step. functionObject used.
• In step 5 we run the simulation and save the log file. Notice that we are • By the way, we are saving a large amount of information.
sending the job to background.
• This is typical of unsteady simulations, and sometimes it can be too daunting
• In step 6 we use pyFoamPlotWatcher.py to plot the residuals on-the-fly. to post-process and analyze the data.
As the job is running in background, we can launch this utility in the same
terminal tab. • To ease the pain of doing data analytics and post-processing, you can use
shell scripting or Python scripting.
• Finally, in step 7 we visualize the solution.
• Hereafter, we are going to address how to use shell scripting.
654 655
writeControl outputTime;
timeStart 0; Output frequency • Here after we are going to study a few commonly used functionObjects.
timeEnd 20;
658 659
51 functions • Let us take a look at the bottom of the controlDict 56 minmaxdomain • fieldMinMax functionObject
57 {
52 { dictionary file. 58 type fieldMinMax;
59 • This functionObject is used to compute the
name_of_the_functionObject_dictionary • Here we define functionObjects, which are functions that 60 functionObjectLibs ("libfieldFunctionObjects.so"); minimum and maximum values of the field
61
{
Dictionary with the functionObject entries
will do a computation while the simulation is running. 62 enabled true; variables.
63
}
• In this case, we define the functionObjects in the sub- 64
65
mode component; • The output of this functionObject is saved in
dictionary functions (lines 51-115). 66 writeControl timeStep; ascii format in the file fieldMinMax.dat located
113 #include "functionObject0" 67 writeInterval 1;
in the directory
114
115 }
• Each functionObject we define, has its own name and its 68
69 log true;
compulsory keywords and entries. 70 postProcessing/minmaxdomian/0
71 fields (p U);
• Notice that in line 113 we use the directive include to call an 72 }
Note:
Use the banana method to know all the options available
for each entry.
660 661
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
The controlDict dictionary The functionObject0 dictionary
Note: Note:
Use the banana method to know all the options available Use the banana method to know all the options available
for each entry. for each entry.
662 663
Note: Note:
Use the banana method to know all the options available Use the banana method to know all the options available
for each entry. for each entry.
664 665
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
The functionObject0 dictionary The functionObject0 dictionary
127 pressureDrop
128 { • fieldValueDelta functionObject 171 innerpatch_massflow • faceSource functionObject
172 {
129 type fieldValueDelta;
173 type surfaceRegion;
130 functionObjectLibs ("libfieldFunctionObjects.so"); • This functionObject is used to compute the 174 functionObjectLibs ("libfieldFunctionObjects.so"); • This functionObject is used to compute the
131 enabled true;
132 difference/average/min/max of two field values. 175 enabled true; mass flow in an inner patch.
176
133 region1
177 writeControl timeStep;
134 { • We are using the operation sum with the field phi. 178 writeInterval 1; • In this case, we are sampling the faceZone
135 writeFields off;
137 type surfaceRegion; This is equivalent to compute the mass flow. 179
180 log true;
internalfacepatch.
138 regionType patch;
181 writeFields false;
139 name inlet; • We are using the operation subtract between the 182 • We are using the operation sum with the field phi.
140
141 operation sum; two field values. 183 regionType faceZone;
142
184 Name internalfacepatch; • The output of this functionObject is saved in
185
143 fields • The output of this functionObject is saved in 186 operation sum; ascii format in the file faceSource.dat located
144 (
145 phi ascii format in the file fieldValueDelta.dat 187
188
fields
(
in the directory
146
147 }
);
located in the directory 189 phi
postProcessing/innerpatch_massflow/0
190 );
148
149 region2 postProcessing/pressureDrop/0 191
192 }
150 {
151 writeFields off;
153 type surfaceRegion; • Remember, the name of the directory where the output
154 regionType patch;
155 name outlet; • Remember, the name of the directory where the output data is saved is the same as the name of the
156
157 operation sum;
data is saved is the same as the name of the functionObject (line 171).
158 functionObject (line 127).
159 fields
160 (
161 phi
162 );
163 } Note: Note:
164 Use the banana method to know all the options available Use the banana method to know all the options available
165 operation subtract;
166 } for each entry. for each entry.
666 667
Note: Note:
Use the banana method to know all the options available Use the banana method to know all the options available
for each entry. for each entry.
668 669
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
Running functionObjects a-posteriori • In the directory system, you will find the following functionObjects
dictionaries: functionObject1 , functionObject2 ,
• Sometimes it can happen that you forget to use a functionObject or you functionObject3 , functionObject4, functionObject5 ,
want to execute a functionObject a-posteriori (when the simulation is over). functionObject6.
• The solution to this problem is to use the solver with the option • Try to figure out what we are doing in every functionObject dictionary.
-postProcess. This will only compute the new functionObject, it will not
rerun the simulation. • At this point, let us run each the functionObject a-posteriori. In the terminal
type:
• For instance, let us say that you forgot to use a given functionObject. Open
the dictionary controlDict, add the new functionObject, and type in the
terminal, 1. $> pisoFoam -postProcess -dict system/functionObject1 > log_fo1
670 671
• In this step 6, we are reading the dictionary functionObject6 and we are • $> awk '1 == NR % 2' out.txt > pre_minmax.txt
672 673
On-the-fly postprocessing – functionObjects On-the-fly postprocessing – functionObjects
Some shell and awk scripting Some shell and awk scripting
• To erase the header of the file pre_minmax.txt, type in the terminal: • In the directory scripts (located in the top level case directory) you will find the following
• $> awk '{if (NR!=1) {print}}' pre_minmax.txt > tmp scripts that will do some data processing automatically,
• script_cleanfile
• $> mv tmp pre_minmax.txt
• script_cleanforce
• To erase the header of the file vel_minmax.txt, type in the terminal: • script_extractfields
• $> awk '{if (NR!=1) {print}}' vel_minmax.txt > tmp • script_force_coe
• $> mv tmp vel_minmax.txt • script_forces
• To compute the mean value of the seventh column of the file pre_minmax.txt (maximum • script_meanvalues
pressure in this case), type in the terminal: • script_minmax
• $> awk 'NR>=50 && NR { total += $7; count++} END { print • script_probes
“Mean_value ” total/count}' pre_minmax.txt
We are computing the mean value of column 7 starting from row 50 • To run the scripts you need to be inside the scripts directory. In the terminal type,
• To compute the mean value of the seventh column of the file vel_minmax.txt (minimum Z • cd scripts
velocity component in this case), type in the terminal: • sh script_name
• $> awk 'NR>=50 && NR { total += $5; count++} END { print
“Mean_value ” total/count}' vel_minmax.txt • Feel free to reuse them and adapt these scripts according to your needs.
We are computing the mean value of column 7 starting from row 50
674 675
• The script script_minmax will extract the minimum and maximum values of the 2. $> gnuplot
field variables.
3. gnuplot> plot [][] 'vel_minmax.txt' u 1:5 w l title "min v_z",
• The script script_probes will extract the information of the probes. '' u 1:11 w l title "max v_z"
We just showed how to compute the average and standard deviation and do some
manipulation of the information saved in the output files, but you can do many things in
an automatic way.
• Let us do some plotting using gnuplot. Type in the terminal (you must be inside the 1. Sampling with the postProcess utility
scripts directory):
2. Probing with the postProcess utility
1. gnuplot> plot [][] '< sed "s/[()]/ /g"
../postProcessing/forces_object/0/forces.dat' u 1:7 w l 3. On-the-fly postprocessing – functionObjects and the
postProcess utility
• In this step we are using sed inside gnuplot to clean the parentheses. If you do not 4. Field manipulation
erase the parentheses in the input file, gnuplot will complain.
5. Co-processing
6. Data conversion
7. foamLog
678 679
$PTOFC/postprocessing/supersonic_cyl/
Density Vorticity Z
www.wolfdynamics.com/wiki/postprocess/ani_rho.gif www.wolfdynamics.com/wiki/postprocess/ani_vortZ.gif
• We will use this case to introduce the postProcess utility. • Let us do some data manipulation. To run the case, type in the terminal:
• We will also show how to run the solver with the option -postProcess. This will let
us do only the post-processing after the solution has been computed, and it will let us 1. $> foamCleanTutorials
access the database of the solver.
2. $> blockMesh
• To find the numerical solution we will use the solver sonicFoam.
3. $> sonicFoam > log.sonicfoam &
• sonicFoam is a transient solver for trans-sonic/supersonic, laminar or turbulent flow
4. $> pyFoamPlotWatcher.py log.sonicfoam
of compressible gas.
5. $> paraFoam
• At the end, we will do some plotting (using gnuplot or Python) and scientific
visualization.
• You do not need to run the simulation until the end time,
• Just run the simulation until 0.2 seconds. We only need a few timesteps to
do the field manipulation.
684 685
Field manipulation Field manipulation
• After finding the solution, we can compute new field variables using the • In step 1 we compute the Mach number. To compute this value, the
primitive variables computed during the solution stage. In the terminal type: postProcess utility needs to access the thermophysicalProperties
dictionary.
1. $> sonicFoam -postProcess -func MachNo • In step 2 we compute the Courant number. To compute this value, the
2. $> sonicFoam -postProcess -func CourantNo postProcess utility needs to access the face fluxes (phi).
3. $> sonicFoam -postProcess -func wallShearStress • In step 3 we compute the wall shear stress. To compute this value, the
postProcess utility needs to access the transport and turbulence
4. $> sonicFoam -postProcess -func 'writeObjects(rho)' -time 0
properties.
5. $> sonicFoam -postProcess -func vorticity
• In step 4 we compute the density (rho) for the initial time (time = 0). To
6. $> postProcess -func vorticity compute this value, the postProcess utility needs to access the simulation
database.
• If the new field variables require information of the simulation database • In steps 5 and 6 we compute the vorticity field, this field is derived from the
(fluxes, turbulence properties, transport properties), you will need to process velocity field. The postProcess utility does not need to access any
as in steps 1-5. particular solver information. Both options will give the same output.
• In the new field variable only requires to use a variable that already exist in
the solution folder, you can proceed as in step 6.
686 687
690 691
Co-processing Co-processing
• CFD simulations have the potential to overwhelm any computer with the output • For unsteady and big simulations, co-processing is an alternative if we do
obtained from simulations. not want to overflow the system with tons of data.
• The traditional approach is to run a simulation and save the solution at given time- • By doing co-processing, we can do visualization on-the-fly.
steps or intervals for post processing at a later time.
• In principle, co-processing is similar to doing sampling using
• An alternative way to do post processing, is to extract results (or pretty pictures) while
functionObjects, but when we do co-processing we output pretty pictures
the simulation is running (on-the-fly), this is co-processing.
(e.g., streamlines, iso-surfaces, cut-planes).
• Instead, when we do sampling using functionObject we save data for
GEOMETRY
plotting (we save a quantity of interest).
• An added benefit of co-processing is that results can be immediately
MESH reviewed and problems can be immediately addressed.
• Co-processing requires that you identify what you want to see before
running the simulation. You need to plan everything in advanced.
SOLVER CO-PROCESSING
• In OpenFOAM®, you can output on-the-fly streamlines, cutting planes, iso-
surfaces, near surface fields, forces and force coefficients (they can be
POST-PROCESSING
written into data bins).
692 693
Co-processing Co-processing
$PTOFC/postprocessing/vespacoarse/
Co-processing Co-processing
What are we going to do? Running the case
• We will use this case to do co-processing using functionObjects. • In the terminal window type:
• We do not need to generate the mesh or run the simulation for a long time. 1. $> foamCleanTutorials
However, all the dictionaries are included.
3. $> rm –f 0
• The dictionaries to initialize the solution using potentialFoam are also $> cp –r 0_org 0
4.
included
5. $> tar –xzvf constant.tar.gz
• We will run the simulation for 20 iterations and then we will visualize the
6. $> cp system/simplefoam/* system/
solution.
7. $> simpleFoam > log | tail –f log
• In this case, we will use the solver simpleFoam with turbulence modeling,
8. $> paraFoam
and we will run in serial, but feel free to run in parallel.
698 699
Co-processing Co-processing
The cuttingPlane dictionary The cuttingPlane dictionary output
31 • Planes sampled using functionObjects.
32 yNormal Name of the plane
33
34
{
type cuttingPlane;
• Each plane contains the information of the fields sampled (U, p, k and omega).
35 planeType pointAndNormal;
36 pointAndNormalDict
37 {
38 basePoint (0 0 0);
39 normalVector (0 1 0); Plane type and plane location
40 }
41 interpolate true;
42 }
43
44 zNormal Name of the plane
45 {
46 type cuttingPlane;
47 planeType pointAndNormal;
48 pointAndNormalDict
49 {
50 basePoint (0 0 1);
51 normalVector (0 0 1); Plane type and plane location
52 }
53 interpolate true;
54 }
55
56
57
);
• The output of this functionObject is saved in the
58 } directory postProcessing/cuttingPlane
• In this directory, you will find many time directories
with the sampled data.
• Inside each directory you will find a series of files
with the VTK extension, you can open these files
in paraFoam/paraview
700 701
Co-processing Co-processing
The streamLines dictionary The streamLines dictionary
• In this dictionary we define the streamlines. 38
39 // Seeding method. See the sampleSets in sampleDict.
• Remember, we need to know the location from where to 40 seedSampleSet uniform; Seed type
41
release the streamlines a priori. 42 uniformCoeffs
43 {
44 type uniform; Options related to the seeding of the streamlines
1 streamLines Name of the functionObject 45 axis x; //distance;
2 { 46
3 type streamLine; 48 start (-1 0 0);
4 49 end (-1 0 1.6);
5 //writeControl outputTime; 50 nPoints 20;
6 51 }
7 52 }
8 writeControl timeStep; Saving frequency. Can be different from
9 writeInterval 5;
10
the saving frequency of the solution
11
12 setFormat vtk;
13
14 // Velocity field to use for tracking.
15 UName U; Velocity field used to compute the streamlines
16
17 // Tracked forwards (+U) or backwards (-U)
• The output of this functionObject is saved in the
18 trackForward true; directory
19
20 //Names of fields to sample. Mustcontain velocity field! postProcessing/sets/streamLines
21 fields (U p); Fields to sample
22 • In this directory, you will find many time directories
23 // Steps particles can travel before being removed
24 lifeTime 10000; with the sampled data.
25
• Inside each directory you will find a series of files
with the VTK extension, you can open these files
in paraFoam/paraview
702 703
Co-processing Co-processing
The streamLines dictionary output The system/files/isoSurface dictionary
• Streamlines sampled using functionObjects. • In this dictionary we define the iso-surfaces.
• Each streamlines contains the information of the fields sampled (U and p). • Remember, we need to know the value of the iso-
surface a priori.
704 705
Co-processing Co-processing
The system/files/isoSurface dictionary The system/files/isoSurface dictionary output
35 interpolatedIso Name of the iso-surface
• Iso-surfaces sampled using functionObjects.
36 {
37
38
// Iso surface for interpolated values only
type isoSurface;
• Each iso-surface contains the information of the fields sampled (U, p, k and omega).
39 isoField p; Field used to create the iso-surface
40 isoValue 80;
41 interpolate true;
and its value
48
49 }
50
62
63 );
64
65
66 }
706 707
3. On-the-fly postprocessing – functionObjects and the • If you are looking for a specific format and it is not supported, you can write your own
conversion tool.
postProcess utility
• In the directory $FOAM_UTILITIES/postprocessing/dataConversion, you will
4. Field manipulation find the source code of the following data conversion utilities:
• To get more information on how to use a data conversion utility, you can read the
source code or type in the terminal:
• $> name_of_data_conversion_utility -help
708 709
Data conversion Roadmap
ASCII ↔ Binary conversion
• Another utility that might come in handy, specially when dealing with
large meshes is foamFormatConvert.
1. Sampling with the postProcess utility
17
18
application icoFoam; • This utility converts the mesh and field variables into ascii or binary 2. Probing with the postProcess utility
19 startFrom startTime; format.
20
21
22
startTime 0; • In order to manually edit the boundary file and the field variables 3. On-the-fly postprocessing – functionObjects and the
23
24
stopAt endTime; dictionaries (initial and boundary conditions), they must be in ascii
format.
postProcess utility
25 endTime 50;
4. Field manipulation
26
27 deltaT 0.01; • After editing these files, we can convert them into binary format.
28
29 writeControl runTime;
• Working in binary format can significantly reduce data parsing and
30
31
32
writeInterval 1; dimension of the files (specially for large meshes). 5. Co-processing
33 purgeWrite 0;
• The drawback is that the files are not human readable anymore.
34
35 writeFormat binary;
6. Data conversion
36 • To convert ascii files into binary files, just type in the terminal:
37
38
39
writePrecision 8;
writeCompression off;
• $> foamFormatConvert 7. foamLog
40
41 timeFormat general; • Remember you will need to set the keyword writeFormat to binary
42
43 timePrecision 6;
in the controlDict dictionary.
44
45 runTimeModifiable true; • In the same way, if you want to convert from binary to ascii, set the
keyword writeFormat to ascii in the controlDict dictionary and
type in the terminal:
• $> foamFormatConvert
710 711
foamLog foamLog
• During execution, OpenFOAM® writes values of residuals, number of • By default, the files are presented in two-column format of time and the
iterations, and so on, on the standard output (terminal). extracted values.
• It is possible to extract this information with the foamLog utility, provided the • You can plot each file by using gnuplot or your favorite plotting tool.
standard output has been written to a log file. • Depending of your case setup, you will find the following files:
• To extract the information, type in the terminal
contCumulative_0 Time
• $> foamLog log_file_name contGlobal Ux
contLocal UxFinalRes
• All the information extracted from the log file is saved in the directory logs CourantMax UxIters
CourantMean Uy
• To plot this info we can use gnuplot, grace, xmgr, octave, qtiPlot, Python,
executionTime UyFinalRes
jPlot (just to name a few).
p UyIters
pFinalRes Uz
pFinalRes_0 UzFinalRes
pIters UzIters
Separator
712 713
foamLog foamLog
• Let us analyze the log file of the previous tutorial. In the terminal type: • This is a screenshot on my workstation. This is a plot of the pressure initial
and final residuals using gnuplot. You can plot any of the output files
1. $> foamLog log generated by foamLog.
2. $> cd logs
3. $> ls -al
4. $> gnuplot
• Let us plot the extracted data using gnuplot. In the terminal type:
714 715
Roadmap
Module 6 2.
3.
On the CFL number
Numerical playground
Finite volume method overview 4. Linear solvers in OpenFOAM®
5. Pressure-Velocity coupling in OpenFOAM®
6. Unsteady and steady simulations
7. Understanding residuals
8. Boundary and initial conditions
716 717
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,
• 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.
• We want to solve the general transport equation for the transported quantity in a • As consequence of the previous requirement, all dependent variables are assumed
given domain, with given boundary conditions BC and initial conditions IC. to vary linearly around a point P in space and instant t in time,
• 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.
• 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)
718 719
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 • In the FVM, a lot of overhead goes into the data book-keeping of the domain information.
cells, such as the one 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
centroid of the control volume. Therefore the notation .
• The control volumes can be of any shape (e.g., tetrahedrons, hexes, prisms,
pyramids, dodecahedrons, and so on). • The vector from the centroid P of to the centroid N of is named d.
• We also know all neighbors of the control volume .
• The only requirement is that the elements need to be convex and the faces that made
up the control volume need to be planar. • The control volume faces are labeled f, which also denotes the face center.
• The location where the vector d intersects a face is .
• We also know which control volumes are internal and which control volumes lie on
• The face area vector point outwards from the control volume, is located at the face
the boundaries.
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.
720 721
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• In the control volume illustrated, the centroid P is given by, • Let us recall the Gauss or Divergence theorem,
• Finally, we assume that the values of all variables are computed and stored in the • The Gauss or Divergence theorem simply states
centroid of the control volume and that they are represented by a piecewise that the outward flux of a vector field through a
constant profile (the mean value), closed surface is equal to the volume integral of
the divergence over the region inside the surface.
• This theorem is fundamental in the FVM, it is
used to convert the volume integrals appearing in
the governing equations into surface integrals.
• This is known as the collocated arrangement.
• All the previous approximations are at least second order accurate.
722 723
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
• Let us use the Gauss theorem to convert the volume integrals into surface integrals, • Integrating in space each term of the general transport equation and by using Gauss
theorem, yields to the following discrete equations for each term
Convective term:
Gauss theorem:
• At this point the problem reduces to interpolating somehow the cell centered values
(known quantities) to the face centers.
724 725
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 where we have approximated the centroid gradients by using the Gauss theorem.
volume integrals into surface integrals by means of the mid point rule, which is This method is second order accurate
second order accurate
726 727
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 • Using the previous equations to evaluate the general transport equation over all the
theorem, yields to the following discrete equations for each term control volumes, we obtain the following semi-discrete equation
Source term:
This approximation is exact if is either constant or varies linearly within the control
volume; otherwise is second order accurate. where is the convective flux and is the
Sc is the constant part of the source term and Sp is the non-linear part
diffusive flux.
Gauss theorem: • 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.
728 729
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes Interpolation of the convective fluxes
• By looking the figure below, the face values appearing in the convective flux can be • By looking the figure below, the face values appearing in the convective flux can be
computed as follows, computed as follows,
• This type of interpolation scheme is known as linear interpolation or central • This type of interpolation scheme is known as upwind differencing and it is first order
differencing and it is second order accurate. accurate.
• However, it may generate oscillatory solutions (unbounded solutions). • This scheme is bounded (non-oscillatory) and diffusive.
730 731
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 • To prevent oscillations in the SOU, we add a gradient or slope limiter function .
computed as follows,
• 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.,
UD = upwind
SOU = second order upwind
CD = central differencing
D = downwind
734 735
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Linear and non-linear limiter functions Interpolation of the convective fluxes – Linear and non-linear limiter functions
• Let us see how the superbee, minmod and vanleer TVD schemes behave in a • Comparison of linear upwind method (2nd order) and upwind method (1st order).
numerical schemes killer test case. • The upwind method is extremely stable and non-oscillatory. However is highly
• The oblique double step profile in a uniform vector field (pure convection). diffusive.
736 737
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Linear and non-linear limiter functions Interpolation of the convective fluxes – Unstructured meshes
• Let us see how the linear and non-linear limiter functions compare. • All higher-order schemes we have seen so far assume line structure (figure A).
• That is, the cell centers PP, P, and N are all aligned.
• In unstructured meshes, it is not straightforward to use the previous schemes, as the cell center
PP is not aligned with the vector connecting cells P and N (figure B).
• Higher-order schemes for unstructured meshes are an area of active research and new ideas
continue to emerge.
738 739
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of the convective fluxes – Unstructured meshes Interpolation of convective fluxes in a skew mesh
• A simple way around this problem is to redefine • In the case of a skew mesh (as the one in the figure), we should introduce a correction in order to maintain
higher-order schemes in terms of gradients at the second order accuracy and avoid unboundedness when computing gradients.
control volume P. • One way of doing this is by using an iterative approach for computing successively better approximations to
the gradients.
• For example, using the gradient of the cells, we can
compute the face values as follows, • We can do a linear reconstruction of the cell and face gradients using compact stencils as follows.
1.
Upwind →
Central difference → 2.
• Notice that in this new formulation the cell PP does not appear any more. Initial approximations
• The problem now turns in the accurate evaluation of the gradients at the cell and face centers.
This can be done using Gauss method as previously explained.
740 741
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Interpolation of diffusive fluxes in a orthogonal mesh Interpolation of diffusive fluxes in a non-orthogonal mesh
• By looking the figures below, the face values appearing in the diffusive flux in an • By looking the figures below, the face values appearing in the diffusive flux in a non-
orthogonal mesh can be computed as follows, orthogonal mesh ( ) can be computed as follows,
• This is a central difference approximation of the first order derivative. This type of
approximation is second order accurate. • This type of approximation is second order accurate but involves a larger truncation
error. It also uses a larger numerical stencil, which make it less stable.
742 743
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
744 Orthogonal and skew mesh Non-orthogonal and skew mesh 745
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/
748 749
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.
750 751
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). • vanLeer: 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.
752 753
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 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
corrections.
Interpolation method of the diffusion coefficient
• corrected: for meshes with grading and non-orthogonality. Second order accurate,
bounded depending on the quality of the mesh, with non-orthogonal corrections. • Setting to 1 is equivalent to using the corrected method. You gain accuracy, but the solution
• limited: for meshes with grading and non-orthogonality. Second order accurate, might become unbounded.
bounded depending on the quality of the mesh, with non-orthogonal corrections.
• By setting the blending factor equal to 0 is equivalent to using the uncorrected method. You
• uncorrected: usually used on bad quality meshes with grading and non-orthogonality. give up accuracy but gain stability.
Second order accurate, without non-orthogonal corrections. Stable but more diffusive
• If you set the blending factor to 0.5, you get the best of both worlds. In this case, the non-
than the limited and corrected methods.
orthogonal contribution does not exceed the orthogonal part. You give up accuracy but gain
stability.
758 759
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
Laplacian terms discretization schemes Laplacian terms discretization schemes
• The limited method uses a blending factor . • The surface normal gradients terms usually use the same method as the one chosen for the
Surface normal gradients discretization Laplacian terms.
• For instance, if you are using the limited 1 method for the Laplacian terms, you can use the
laplacianSchemes Only option same method for snGradSchemes:
{
default Gauss linear limited ;
}
laplacianSchemes
{
Interpolation method of the diffusion coefficient
default Gauss linear limited 1;
}
• For meshes with non-orthogonality less than 75, you can set the blending factor to 1.
snGradSchemes
• For meshes with non-orthogonality between 75 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 default limited 1;
definitely want to use that mesh, you can set the blending factor to 0.333, and increase the }
number of non-orthogonal corrections.
• If you are doing LES or DES simulations, use a blending factor of 1 (this means that you need
good meshes).
760 761
Finite Volume Method: A Crash introduction Finite Volume Method: A Crash introduction
What method should I use? A very accurate but oscillatory numerics
ddtSchemes • This setup is recommended for most of ddtSchemes • If you are looking for more accuracy, you can use
{ {
default CrankNicolson 0;
the cases. default backward;
this method.
} }
gradSchemes • It is equivalent to the default method you will find in gradSchemes • In overall, this setup is second order accurate but
{ commercial solvers. { oscillatory.
default cellLimited Gauss linear 1; default Gauss leastSquares;
grad(U) cellLimited Gauss linear 1; • In overall, this setup is second order accurate and } • Use this setup with LES simulations or laminar
} divSchemes
divSchemes
fully bounded. { flows with no complex physics, and meshes with
{ default none; overall good quality.
default none;
• According to the quality of your mesh, you will need div(phi,U) Gauss linear;
div(phi,U) Gauss linearUpwindV grad(U); to change the blending factor of the div(phi,omega) Gauss linear; • Use this method with good quality meshes.
div(phi,omega) Gauss linearUpwind default; laplacianSchemes and snGradSchemes div(phi,k) Gauss linear;
div(phi,k) Gauss linearUpwind default; div((nuEff*dev(T(grad(U))))) Gauss linear;
keywords. }
div((nuEff*dev(T(grad(U))))) Gauss linear;
laplacianSchemes
}
laplacianSchemes
• To keep temporal diffusion to a minimum, use a CFL {
{ number less than 2. }
default Gauss linear limited 1;
default Gauss linear limited 1;
interpolationSchemes
} • If during the simulation the turbulence quantities {
interpolationSchemes
{
become unbounded, you can safely change the default linear;
}
default linear; discretization scheme to upwind. After all, snGradSchemes
}
snGradSchemes
turbulence is diffusion. {
default limited 1;
{
}
default limited 1;
}
762 763
764 765
On the CFL number On the CFL number
• First at all, what is the CFL or Courant number? • Let us talk about the CFL number condition.
• In one dimension, the CFL number is defined as, • The CFL number condition is the maximum allowable CFL number a numerical
scheme can use.
• For the N dimensional case, the CFL number condition becomes,
• By doing a linear stability study, we can find the stability requirements of each • Explicit and implicit methods are approaches used for obtaining the approximate
numerical scheme (but this is out of the scope of this lecture). numerical solution of time-dependent ODEs and PDEs.
• Explicit and implicit methods have different stability requirements.
• Also, the implementation details are different.
766 767
768 769
On the CFL number On the CFL number
Some facts of explicit and implicit methods The CFL number for dummies
• For the same CFL number, the time-step of explicit methods is usually an order of magnitude lower than the • I like to see the CFL number as follows,
time-step required for implicit methods.
• This means that they are approximately ten times slower than implicit methods.
• Explicit methods are extremely accurate, but they have terrible time steps constraints.
• The memory requirements are really low and they are extremely easy to parallelize.
• Explicit methods perform really well in GPUs.
• Also, explicit methods are extremely fast (clock time per iteration), and easy to implement • It is an indication of the amount of information that
• In order to arrive to a converged solution you will need to perform a lot of iterations. This is mainly related to the
propagates through one cell (or many cells), in one
time step constraint.
• If you are interested in using large time steps (large CFL number) you will need to use implicit methods.
time-step.
• Due to the fact that implicit methods let you use large time steps, you can arrive to a converge solution much
faster than with explicit methods.
• Also, implicit methods tend to be more stable than explicit methods.
• It is highly advisable that you choose a time step in such a way that it resolves the temporal scales. • By the way, and this is extremely important, the CFL condition is a necessary
• If you use large time steps with implicit methods, it is likely that you will need to increase the cell count in order condition for stability (and hence convergence).
to maintain the accuracy of the solution, and this translates in an increased computational cost.
• But it is not always sufficient to guarantee stability.
• In our personal experience, we have been able to go up to a CFL = 5.0 while maintaining the accuracy and
without increasing too much the computational cost. • Other properties of the discretization schemes that you should observe are:
• But as we are often interested in the unsteadiness of the solution, we usually use a CFL number in the order of conservationess, boundedness, transportiveness, and accuracy.
1.0
• The CFL number is not a magical number!
770 771
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 easiest way is by changing the time-step size. startTime 0;
• When any of these conditions is reached, the solver will stop
stopAt endTime; • If you refine the mesh, and you would like to have the same stopAt endTime;
scaling the time-step size.
endTime 10; CFL number as the base mesh, you will need to decrease the endTime 10;
deltaT 0.0001;
time-step size. deltaT 0.0001;
• To use these features, you need to turn-on the option
adjustTimeStep.
writeControl runTime; • On the other side, if you coarse the mesh and you would like writeControl runTime;
writeInterval 0.1;
to have the same CFL number as the base mesh, you will writeInterval 0.1;
• Remember, the first time step of the simulation is done using
need to increase the time-step size. the value defined with the keyword deltaT and then it is
purgeWrite 0; purgeWrite 0;
automatically scaled (up or down), to achieve the desired
• The keyword deltaT controls the time-step size of the
writeFormat ascii; writeFormat ascii; maximum values (maxCo and maxDeltaT).
simulation (0.0001 seconds in this generic case).
writePrecision 8; writePrecision 8;
• It is recommended to start the simulation with a low time-step
• If you use a solver that supports adjustable time-step
writeCompression off; writeCompression off;
in order to let the solver scale-up the time-step size.
(adjustTimeStep), you can set the maximum CFL number
timeFormat general; timeFormat general;
and maximum allowable time-step using the keywords • If you want to change the values on-the-fly, you need to turn-
timePrecision 6;
maxCo and maxDeltaT, respectively. timePrecision 6;
on the option runTimeModifiable.
runTimeModifiable yes; runTimeModifiable yes;
• 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;
772 773
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. Numerical playground
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. Linear solvers 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. Pressure-Velocity coupling in OpenFOAM®
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. Unsteady and steady simulations
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. Understanding residuals
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. Boundary and initial conditions
yPlus yplus output:
patch square y+ : min = 0.44603573, max = 6.3894913, average = 2.6323389
writing field yPlus
774 775
776 777
Numerical playground Numerical playground
Pure convection of a scalar in a vector field – One dimensional tube. • This problem has an exact solution in the form of a traveling wave.
• We will use this case to study the different discretization schemes implemented in
OpenFOAM®.
• In the figure, we show the solution for time = 0.5 s
www.wolfdynamics.com/wiki/pureconvection/xani1.gif
U = zeroGradient
T = zeroGradient
U = (1 0 0) U = zeroGradient
T=1 T = zeroGradient
(0 0 0) (1 0 0)
U = zeroGradient
T = zeroGradient www.wolfdynamics.com/wiki/pureconvection/xani2.gif
Initial conditions
U = (1 0 0)
T=0
778 779
780 781
Numerical playground Numerical playground
Comparison of different temporal discretization Comparison of Crank Nicolson blending factor using Comparison of Crank Nicolson blending factor using Comparison of Crank Nicolson blending factor using
schemes and gradient limiters. cellLimited leastSquares 0.5 gradient limiter. cellLimited leastSquares 0.5 gradient limiter. cellMDLimited Gauss linear 1.0 gradient limiter.
Linear upwind in space – 100 cells – CFL 0.1 Linear upwind in space – 100 cells – CFL 0.1 Linear upwind in space – 100 cells – CFL 0.1 Linear upwind in space – 100 cells – CFL 0.1
782 783
784 785
Numerical playground Numerical playground
• We will not run this case, this is a visual and mental exercise
only.
• You will find this case in the directory
Slide:
$PTOFC/101FVM/laplace
2D Laplace equation in a square domain.
• In this directory, you will also find the README.FIRST file with
the instructions of how to run the case.
786 787
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
790 791
A B gradSchemes:
A B gradSchemes:
Gauss linear Gauss linear
laplacianSchemes: laplacianSchemes:
Gauss linear orthogonal Gauss linear limited 1
C C
field field
792 793
Numerical playground Numerical playground
2D Laplace equation in a square domain 2D Laplace equation in a square domain
A B gradSchemes:
A B gradSchemes:
Gauss leastSquares Gauss leastSquares
laplacianSchemes: laplacianSchemes:
Gauss linear orthogonal Gauss linear limited 1
C C
field field
794 795
Scalar T
796 797
Numerical playground Numerical playground
Flow in a lid-driven square cavity – Re = 100
Non-orthogonal mesh vs. orthogonal mesh
Swing:
Flow in a lid-driven square cavity – Re = 100
Effect of grading and non-orthogonality on the
accuracy of the solution
• We will use this case to learn how to adjust the numerical schemes according to
mesh non-orthogonality and grading.
798 799
• 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) 800 Journal of computational physics, 48, 387-411 (1982) 801
Numerical playground Numerical playground
How to adjust the numerical method to deal with non-orthogonality How to adjust the numerical method to deal with non-orthogonality
17 ddtSchemes • In the dictionary fvSchemes we can enable non- 17 solvers • Additionally, in the dictionary fvSolution we need to
18 { 18 {
19 default backward; orthogonal corrections. 19 p define the number of PISO corrections (nCorrectors) and
20 } 20 { non-orthogonal corrections (nNonOrthogonalCorrectors).
21 • Non-orthogonal corrections are chosen using the 21 solver PCG;
22 gradSchemes 22 preconditioner DIC;
23 { keywords laplacianSchemes and snGradSchemes. 23 tolerance 1e-06; • You need to do at least one PISO correction. Increasing the
24 default Gauss linear; 24 relTol 0; number of PISO correctors will improve the stability and
25 //default cellMDLimited Gauss linear 1; • These are the laplacianSchemes and 38 }
26 39 accuracy of the solution at a higher computational cost.
27 grad(p) Gauss linear; snGradSchemes schemes that you will use most of the 40 pFinal
28
29
}
times: 41
42
{
$p;
• For orthogonal meshes, 1 PISO correction is ok. But as
30 divSchemes 43 relTol 0; most of the time you will deal with non-orthogonal meshes,
31 { • orthogonal: second order accurate, bounded on 44 }
doing 2 PISO corrections is a good choice.
32
33
default
//div(phi,U)
none;
Gauss linearUpwind default;
perfect meshes, without non-orthogonal 45
46 U
34 div(phi,U) Gauss linear; corrections. 47 { • If you are using a method with non-orthogonal corrections
35 } 48 solver smoothSolver;
36 • corrected: second order accurate, bounded 49 smoother symGaussSeidel; (corrected or limited 1-0.5), you need to define the number
37
38
laplacianSchemes
{ depending on the quality of the mesh, with non-
50
51
tolerance
relTol
1e-08;
0;
of non-orthogonal corrections (nNonOrthogonalCorrectors).
39
40
default
//default
Gauss linear orthogonal;
Gauss linear limited 1;
orthogonal corrections. 52
53 }
}
• If you use 0 nNonOrthogonalCorrectors, you are
41
42
}
• limited : second order accurate, bounded
54
55 PISO
computing the initial approximation using central differences
43 interpolationSchemes depending on the quality of the mesh, with non- 56 { (accurate but unstable), with no explicit correction.
44 { 57 nCorrectors 1;
45 default linear; orthogonal corrections. 58 nNonOrthogonalCorrectors 0;
• To take into account the non-orthogonality of the mesh, you
46 } 59 pRefCell 0;
47 • uncorrected: second order accurate, without 60 pRefValue 0; will need to increase the number of corrections (you get
48 snGradSchemes 61 }
49 { non-orthogonal corrections. Stable but more better approximations using the previous correction).
50
51
default
//default
orthogonal;
limited 1;
diffusive than limited and corrected. • Usually 2 nNonOrthogonalCorrectors is ok.
52 }
802 803
• We will use the lid-driven square cavity case to study the effect of grading • The only difference is that we have modified the mesh a little bit in order to add
grading and non-orthogonality.
and non-orthogonality on the accuracy of the solution
• After generating the mesh, we will use the utility checkMesh to control the quality of
• This case is located in the directory:
the mesh. Is it a good mesh?
• We will use this case to learn how to adjust the numerical schemes according to
mesh non-orthogonality and grading.
$PTOFC/101FVM/nonorthoCavity/
• To find the solution we will use icoFoam.
• After finding the numerical solution we will do some sampling.
• At the end, we will do some plotting (using gnuplot or Python) and scientific
visualization.
• From this point on, please follow me.
• We are all going to work at the same pace.
• Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
804 805
Numerical playground Numerical playground
Running the case To run the case, follow these steps
• You will find this tutorial in the directory $PTOFC/101FVM/nonorthoCavity • First run the case using the original dictionaries. Did it crash right?
• In the terminal window type: • Now change the laplacianSchemes and snGradSchemes to limited 1. It crashed again but
this time it ran a few more time-steps, right?
• Now increase the number of nNonOrthogonalCorrectors to 2. It crashed again but it is running
1. $> foamCleanTutorials more time-steps, right?
2. $> blockMesh • Now increase the number of PISO corrections to 2 (nCorrectors). Did it run?
3. $> checkMesh • Basically we enabled non-orthogonal corrections, we computed better approximations of the
gradients, and we increased the number of PISO corrections to get better predictions of the field
4. $> icoFoam | log variables (U and p).
5. $> postProcess -func sampleDict -latestTime • Now set the number of nNonOrthogonalCorrectors to 0. Did it crash right? This is telling us
that the mesh is sensitive to the gradients.
6. $> gnuplot gnuplot/gnuplot_script
• Now change the laplacianSchemes and snGradSchemes to limited 0 (uncorrected). In this
7. $> paraFoam case we are not using non-orthogonal corrections, therefore there is no need to increase the
value of nNonOrthogonalCorrectors.
• We are using a method that uses a wider stencil to compute the Laplacian, this method is more
stable but a little bit more diffusive. Did it run?
• At this point, compare the solution obtained with corrected and uncorrected schemes. Which
one is more diffusive?
806 807
laplacianSchemes
{
Seesaw:
}
default Gauss linear limited 1; PISO
{ Sod’s shock tube.
nCorrectors 2;
snGradSchemes nNonOrthogonalCorrectors 1;
{ }
default limited 1;
}
• This method works fine for meshes with non-orthogonality less than 75.
• If the non-orthogonality is more than 75, you should consider using limited
0.5, and increasing nCorrectors and nNonOrthogonalCorrectors.
• When the non-orthogonality is more than 85, the best solution is to redo the
mesh.
808 809
Numerical playground Numerical playground
Sod’s shock tube High Purity Photolysis Shock Tube (NASA Tube)
• This case has an analytical solution and plenty of experimental data.
• This is an extreme test case used to test solvers.
• Every single commercial and open source solver use this case for validation of the
numerical schemes.
• The governing equation of this test case are the Euler equations.
Shock tube. The driver section, including vacuum pumps, controls, and helium driver gas.
Photo credit: Stanford University. http://hanson.stanford.edu/index.php?loc=facilities_nasa
810 Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose. 811
www.wolfdynamics.com/wiki/shocktube/anip.gif www.wolfdynamics.com/wiki/shocktube/anigt.gif
• This case is located in the directory: • We will compare your numerical solution with the analytical solution.
• At this point, we are very familiar with the numerical schemes. It is up to you to
choose the best setup.
$PTOFC/101FVM/shockTube/ • You can start using the original dictionaries.
• To find the numerical solution we will use sonicFoam.
• sonicFoam is a transient solver for trans-sonic/supersonic, laminar or turbulent flow
of a compressible gas.
• From this point on, please follow me.
• After finding the numerical solution we will do some sampling.
• We are all going to work at the same pace.
• At the end, we will do some plotting (using gnuplot or Python) and scientific
• Remember, $PTOFC is pointing to the path where you visualization.
unpacked the tutorials.
816 817
Numerical playground Numerical playground
Running the case Running the case
• You will find this tutorial in the directory $PTOFC/101FVM/schockTube • In step 3 we generate the mesh using blockMesh.
• Before running the case, you will need to choose the discretization scheme. • In step 5 and 6 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.
• In the terminal window type:
• In step 7 we initialize the solution using setFields.
1. $> foamCleanTutorials
• In step 8 we run the simulation and save the log file.
2. $> blockMesh
• In step 9 we use the utility foamCalc to compute the magnitude of the velocity vector
3. $> checkMesh U. The output is saved as magU.
4. $> rm –rf 0 • In step 10 we use the utility postProcess to do sampling of the field variables.
5. $> cp –r 0_org 0 • Finally, in step 11 we visualize the solution using paraFoam.
6. $> setFields
7. $> sonicFoam | tee log
8. $> foamCalc mag U
9. $> postProcess -func sampleDict -latestTime
10. $> paraFoam
818 819
• The Python script will save four .png files with the solution. • Computational Methods for Fluid Dynamics
J. H. Ferziger, M. Peric. 2001, Springer
• Feel free to explore and adapt the Python script to your needs. • Numerical Heat Transfer and Fluid Flow
S. Patankar. 1980, Taylor & Francis
• Remember, Python must be installed in order to use the script. • A Finite Volume Method for the Prediction of Three-Dimensional Fluid Flow in Complex Ducts
M. Peric. PhD Thesis. 1985. Imperial College, London
• We use Anaconda Python 2.7 • Error analysis and estimation in the Finite Volume method with applications to fluid flows
H. Jasak. PhD Thesis. 1996. Imperial College, London
• Computational fluid dynamics of dispersed two-phase flows at high phase fractions
H. Rusche. PhD Thesis. 2002. Imperial College, London
• High Resolution Schemes Using Flux Limiters for Hyperbolic Conservation Laws
P. K. Sweby SIAM Journal on Numerical Analysis, Vol. 21, No. 5. (Oct., 1984), pp. 995-1011
820 821
Roadmap Linear solvers in OpenFOAM®
• After spatial and temporal discretization and by using equation
824 825
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
Linear solvers Linear solvers
solvers • The linear solvers distinguish between symmetric matrices and solvers • The linear solvers are iterative, i.e., they are based on reducing
{ asymmetric matrices. { the equation residual over a succession of solutions.
p p
{ • The symmetry of the matrix depends on the structure of the { • The residual is a measure of the error in the solution so that the
solver PCG; solver PCG;
preconditioner DIC;
equation being solved. preconditioner DIC;
smaller it is, the more accurate the solution.
tolerance 1e-06; tolerance 1e-06;
• Pressure is a symmetric matrix and velocity is an asymmetric • More precisely, the residual is evaluated by substituting the
relTol 0; relTol 0;
} matrix. } current solution into the equation and taking the magnitude of
pFinal pFinal the difference between the left and right hand sides (L2-norm).
{ • If you use the wrong linear solver, OpenFOAM® will complain {
$p; and will let you know what options are valid. $p;
relTol 0; relTol 0;
}
• In the following error screen, we are using a symmetric solver }
U for an asymmetric matrix, U
{ {
solver PCG; –> FOAM FATAL IO ERROR : solver PBiCGStab;
• It is also normalized to make it independent of the scale of the
preconditioner DILU; Unknown asymmetric matrix solver PCG preconditioner DILU;
tolerance 1e-08; tolerance 1e-08; problem being analyzed.
relTol 0; relTol 0;
} Valid asymmetric matrix solvers are : }
} }
4
PISO PISO
{
( {
nCorrectors 2; BICCG nCorrectors 2;
nNonOrthogonalCorrectors 1; GAMG nNonOrthogonalCorrectors 1;
} }
P
smoothSolver
) 826 827
832 833
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
Linear solvers Linear solvers
• So how do we set the tolerances? • For the velocity field (U) and the transported quantities (asymmetric matrices), you
• The pressure equation is particularly important, so we should resolve it accurately. can use the following criterion.
Solving the pressure equation is the expensive part of the whole iterative process. • Solving for these variables is relative inexpensive, so you can start right away with a
• For the pressure equation you can start the simulation with a tolerance equal to 1e-6 tight tolerance
and relTol equal to 0.01. After a while you change these values to 1e-6 and 0.0,
respectively.
Loose tolerance Tight tolerance
• If the solver is too slow, you can change the convergence criterion to 1e-4 and relTol
equal to 0.05. You usually will do this during the first iterations.
U U
{ {
Loose tolerance Tight tolerance solver PBiCGStab; solver PBiCGStab;
preconditioner DILU; preconditioner DILU;
tolerance 1e-8; tolerance 1e-8;
relTol 0.01; relTol 0.0;
p p } }
{ {
solver PCG; solver PCG;
preconditioner DIC; preconditioner DIC;
tolerance 1e-6; tolerance 1e-6;
relTol 0.01; relTol 0.0;
} }
834 835
836 837
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
Linear solvers Linear solvers
• When you use the PISO or PIMPLE method, you also have the option to set the • As we are solving a sparse matrix, the more diagonal the matrix is, the best the
tolerance for the final pressure corrector step (pFinal). convergence rate will be.
• By proceeding in this way, you can put all the computational effort only in the last • So it is highly advisable to use the utility renumberMesh before running the
corrector step (pFinal in this case). simulation.
• For all the intermediate corrector steps (p), you can use a more relaxed convergence
criterion. • $> renumberMesh -overwrite
• If you proceed in this way, it is recommended to do at least 2 corrector steps
(nCorrectors).
• The utility renumberMesh can dramatically increase the speed of the linear solvers,
Courant Number mean: 0.10556573 max: 0.65793603
deltaT = 0.00097959184
Time = 10
specially during the firsts iterations.
PIMPLE: iteration 1
DILUPBiCG: Solving for Ux, Initial residual = 0.0024649332, Final residual = 2.3403547e-09, No Iterations 4 • You will find the source code and the master dictionary in the following directory:
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 • $WM_PROJECT_DIR/applications/utilities/mesh/manipulation/renumberMesh
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
Note:
This is the actual pressure matrix from an OpenFOAM® model case 840 841
Linear solvers in OpenFOAM® Linear solvers in OpenFOAM®
On the multigrid solvers tolerances Linear solvers tolerances – Steady simulations
• If you go for the GAMG linear solver for symmetric matrices (e.g., pressure), the • The previous tolerances are fine for unsteady solver.
following tolerances are acceptable for most of the cases. • For extremely coupled problems you might need to have tighter tolerances.
Loose tolerance for p Tight tolerance for pFinal • You can use the same tolerances for steady solvers. However, it is acceptable to use
a looser criterion.
p pFinal
{ { • You can also set the convergence controls based on residuals of fields. The controls
solver GAMG; solver GAMG; are specified in the residualControls sub-dictionary of the dictionary file
tolerance 1e-6; tolerance 1e-6;
relTol 0.01; relTol 0;
fvSolution.
smoother GaussSeidel; smoother GaussSeidel;
nPreSweeps 0; nPreSweeps 0;
nPostSweeps 2; nPostSweeps 2; SIMPLE
cacheAgglomeration on; cacheAgglomeration on; {
agglomerator faceAreaPair; agglomerator faceAreaPair;
nCellsInCoarsestLevel 100; nCellsInCoarsestLevel 100;
nNonOrthogonalCorrectors 2;
mergeLevels 1; mergeLevels 1;
minIter 3; minIter 3; residualControl
} } {
p 1e-4; Residual control for every
U 1e-4; field variable you are solving
NOTE: }
The GAMG parameters are not optimized, that is up to you. }
Most of the times is safe to use the default parameters. 842 843
IC1 PCG FDIC NO 278 2.8265539 1. Finite Volume Method: A Crash Introduction
IC2 smoothSolver symGaussSeidel NO 2070 2.8271198
2. On the CFL number
IC3 ICCG GAMG NO 255 2.8265538
IC8 PCG GAMG-GaussSeidel YES 283 2.8265538 6. Unsteady and steady simulations
IC9 ICCG GAMG YES 261 2.8265538
7. Understanding residuals
IC10 PCG DIC NO 244 2.8265539
8. Boundary and initial conditions
Solver used = icoFoam – Incompressible case
MR = matrix reordering (renumberMesh)
QOI = quantity of interest. In this case the maximum velocity at the outlet (m/s)
TIME = clock time (seconds) 844 845
Pressure-Velocity coupling in OpenFOAM® Pressure-Velocity coupling in OpenFOAM®
• To solve the Navier-Stokes equations we need to use a solution • Many numerical methods exist to solve the Navier-Stokes equations, just to name a few:
• Pressure-correction methods (Predictor-Corrector type).
approach able to deal with the nonlinearities of the governing
• SIMPLE, SIMPLEC, SIMPLER, PISO.
equations and with the coupled set of equations.
• Projection methods.
• Fractional step (operator splitting), MAC, SOLA.
• Density-based methods and preconditioned solvers.
• Riemann solvers, ROE, HLLC, AUSM+, ENO, WENO.
• Artificial compressibility methods.
• Artificial viscosity methods.
• The most widely used approaches for solving the NSE are:
• Pressure-based approach (predictor-corrector).
• Density-based approach.
• Historically speaking, the pressure-based approach was developed for low-speed
incompressible flows, while the density-based approach was mainly developed for high-speed
compressible flows.
Additional equations deriving from models, such as, volume fraction,
• However, both methods have been extended and reformulated to solve and operate for a wide
chemical reactions, turbulence modeling, combustion, multi-species, etc.
range of flow conditions beyond their original intent.
846 847
• For instance, if you are using the PISO method, you will need to specify the • PIMPLE
PISO sub-dictionary. • Unknown origins.
• Useful reference:
• And depending on the method, each sub-dictionary will have different • I. E. Barton, “Comparison of SIMPLE and PISO-type algorithms for transient flows, Int.
J. Numerical methods in fluids, 26,459-483 (1998).
entries.
850 851
correction.
v** = v* + v'
w** = w* + w'
p* = p
u* = u
v* = v
w* = w
Correct pressure and velocities • However, it is strongly recommended to do are 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
852 853
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 reduce. 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;
}
}
}
854 855
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 to use relaxationFactors );
• 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.
• It is clear that this will add an extra computational cost, which is negligible.
• For good accuracy and stability, it is recommended to use 2 nCorrectors.
• 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 • It is recommended to use this option for highly convective flows (high Reynolds number). If you
nNonOrthogonalCorrectors keyword. are working with low Reynolds flow or creeping flows it is recommended to turn it off.
• The number of non-orthogonal correctors is chosen according to the mesh quality. For orthogonal • Remember, when you enable the option momentumPredictor, you will need to define the linear
meshes you can use 0, whereas, for non-orthogonal meshes it is recommended to do at least 1 solvers for the variables .*Final (we are using regex notation).
correction.
PISO
PISO
{
{
momentumPredictor yes;
nCorrectors 2;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
nNonOrthogonalCorrectors 1;
}
}
858 859
PIMPLE
U = HbyA – rAU*fvc::grad(p); {
momentumPredictor yes;
nOuterCorrectors 1;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
}
860 861
Roadmap Unsteady and steady simulations
• A few examples of unsteady applications:
Vortex shedding Buoyant flow
www.wolfdynamics.com/wiki/FVM_uns/ani1.gif www.wolfdynamics.com/wiki/FVM_uns/ani2.gif
• In the controlDict dictionary you need to set runtime parameters and general instructions on how to run the writePrecision 8; • And as the option runTimeModifiable is on (yes), we can
case (such as time step and maximum CFL number). You also set the saving frequency. modify all these entries while we are running the simulation.
writeCompression off;
• In the fvSchemes dictionary you need to set the temporal discretization scheme. timeFormat general;
• In the fvSolution dictionary you need to set the linear solvers. timePrecision 6;
• Also, you will need to set the number of corrections of the velocity-pressure coupling method used (e.g. PISO runTimeModifiable yes;
or PIMPLE), this is done in the fvSolution dictionary.
adjustTimeStep yes;
• Additionally, you may set functionObjects in the controlDict dictionary. The functionObjects are used to maxCo 2.0;
do sampling, probing and co-processing while the simulation is running. maxDeltaT 0.001;
866 867
874 875
876 877
Unsteady and steady simulations Unsteady and steady simulations
What about steady simulations? What about steady simulations?
• First at all, steady simulations are a big simplification of reality. • You also need to set the under-relaxation factors.
• Steady simulations is a trick used by CFDers to get fast outcomes with results that might be • The under-relaxation factors control the change of the variable .
even more questionable.
• As mentioned before, most of the flows you will encounter are unsteady.
• In steady simulations we made two assumptions:
• We ignore unsteady fluctuations. That is, we neglect the temporal derivative in the • If we are using under-relaxation.
governing equations.
• Under-relaxation is a feature typical of steady solvers using the SIMPLE method.
• We perform time averaging when dealing with stationary turbulence (RANS modeling) • If you do not set the under-relaxation factors, OpenFOAM® will use the default hard-wired
• The advantage of steady simulations is that they require low computational resources, give fast values (1.0 for all field variables or no under-relaxation).
outputs, and are easier to post-process and analyze. • These are the under-relaxation factors commonly used with SIMPLE (industry standard),
• In OpenFOAM® is possible to run steady simulation.
• To do so, you need to use the appropriate solver and use the right discretization scheme. p 0.3;
• As you are not solving the temporal derivative, you do not need to set the time step. However, U 0.7;
you need to tell OpenFOAM® how many iterations you would like to run. k 0.7;
• You can also set the residual controls (residualControl), in the fvSolution dictionary file. omega 0.7;
You set the residualControl in the SIMPLE sub-dictionary. epsilon 0.7;
• If you do not set the residual controls, OpenFOAM® will run until reaching the maximum
number of iterations (endTime). • According to the physics involved you will need to add more under-relaxation factors.
• Finding the right under-relaxation factors involved experience and a lot of trial and error.
878 879
890 891
• The first time-steps the solution might not converge, this is acceptable. • It is better to monitor a quantity of interest.
• Also, you might need to use a smaller time-step during the first iterations to maintain • And by the way, you should get physically realistic values.
solver stability. • To monitor the stability, you can check the minimum and maximum values of the field
• You can also increase the number of maximum inner iterations. variables.
• If the initial residuals fall bellow the convergence criterion, you might say that you • If you have bounded quantities, check that you do not have over-shoots or under-
have arrived to a steady solution. shoots.
892 893
Understanding residuals Understanding residuals
• This is the residual plot of an unsteady • And this is the plot of the number of • Let us study the residual plot of an • Let us study the residual plot of an
solver that reached a steady-state inner-iterations against the number of unsteady solution (or flow), using a steady solution (or flow), using a
behavior. outer-iterations (time-steps). steady solver. steady solver.
• Notice that after a couple of thousands • Notice that after 2000 time-steps, the • Notice that we are making the • In this case, the initial residuals are
iterations the initial residuals and final solution arrives to the convergence distinction between steady solver and falling below the convergence
residuals are the same. criterion (in the linear solvers) in just 1 unsteady solution. criterion (monolithic convergence),
• We are plotting the residuals against iteration (in this case we are setting • Here the initial residuals are not falling hence we have reached a steady-
iterations (or time-steps or outer- minIter equal to 1). (stalled convergence). This is an state.
iterations). indication of an unsteady solution or • In comparison to unsteady solvers,
the wrong numerics. steady solvers require less iterations
to arrive to a converge solution, if they
arrive.
894 895
896 897
Understanding residuals Understanding residuals
• Finally, let us compare the residuals of • This is the plot of the number of inner- • However, the fact that the first order method converge faster and is less
a first order and a second order iterations against the number of outer- computationally expensive, it does not mean it is better.
numerical scheme. iterations (time-steps).
• As you can see, first order methods highly under-predict the quantity of
• This is the residual plot of an unsteady • As you can see, the first order method
interest.
simulation. is less computationally expensive.
• In this case, the first order method takes more time to onset the instability.
• Both methods are converging to the • However, the fact that the first order
desired tolerance. method converge faster and is less
• Also, the fact that the residuals drops computationally expensive, it does not
faster using a first order methods, mean it is better.
does not mean that they are better.
898 899
900 901
Understanding residuals Roadmap
• This is the output of the aerodynamic • This is the output of the aerodynamic
coefficients for a Reynolds number coefficients for a Reynolds number
equal to 200 (unsteady case). equal to 20 (steady case).
1. Finite Volume Method: A Crash Introduction
2. On the CFL number
3. Numerical playground
4. Linear solvers in OpenFOAM®
5. Pressure-Velocity coupling in OpenFOAM®
6. Unsteady and steady simulations
7. Understanding residuals
8. Boundary and initial conditions
902 903
Boundary conditions and initial conditions Boundary conditions and initial conditions
On the initial boundary value problem (IBVP) A few words about boundary conditions
• First at all, when we use a CFD solver (OpenFOAM® included) to find the • Boundary conditions can be divided into three fundamental mathematical types:
approximate solution of the governing equations, we are solving an Initial • Dirichlet boundary conditions.
Boundary Value Problem (IBVP).
• Neumann boundary conditions.
• In an IBVP, we need to impose appropriate boundary conditions and initial • Robin Boundary conditions.
conditions.
• When we use a Dirichlet boundary condition, we prescribe the value of a
• No need to say that the boundary conditions and initial conditions need to be variable at the boundary.
physically realistic. • When we use a Neumann boundary condition, we prescribe the gradient
• Boundary conditions are a required component of the numerical method, normal to the boundary.
they tell the solver what is going on at the boundaries of the domain. • Robin boundary conditions, are a mixed of Dirichlet boundary conditions and
Neumann boundary conditions.
• You can think of boundary conditions as source terms.
• You can use any of these three boundary conditions in OpenFOAM®.
• Initial conditions are also a required component of the numerical method,
• During this discussion the semantics is not important, that depends of how you
they define the initial state of the problem.
want to call the boundary conditions or how they are named in the solver, i.e., in,
inlet, inflow, velocity inlet, incoming flow and so on.
904 905
Boundary conditions and initial conditions Boundary conditions and initial conditions
A few words about boundary conditions A few words about boundary conditions
• Defining boundary conditions involves: • To define boundary conditions you need to know the location of the
• Determining the boundary condition type. boundaries (where they are in your mesh), and supply the information at the
boundaries.
• Finding the location of the boundary condition in the domain.
• You must know what information is required at the boundaries, you must
• Giving the required physical information.
know the physics involved.
906 907
Boundary conditions and initial conditions Boundary conditions and initial conditions
A few words about initial conditions A few words about initial conditions
• Initial conditions can be divided into two groups: • Defining initial conditions involves:
• Uniform initial conditions. • Determining the initial condition type.
• Non-uniform initial conditions. • Finding the location of the initial condition in the domain.
• Giving the required physical information.
• For non-uniform initial conditions, the value used can be obtained from:
• Another simulation, including a solution with different grid resolution. • The choice of the initial conditions depend on:
• A potential solver. • Geometrical considerations.
• Experimental results. • Physics involved.
• A mathematical function • Information available.
• Reduced order models. • Numerical considerations.
908 909
Boundary conditions and initial conditions Boundary conditions and initial conditions
A few words about initial conditions A few considerations and guidelines
• For initial conditions, you need to supply the initial information or initial state • Boundary conditions and initial conditions need to be physically realistic.
of your problem. • Poorly defined boundary conditions can have a significant impact on your solution.
• This information can be a uniform value or a non-uniform value. • Initial conditions are as important as the boundary conditions.
• A good initial condition can improve the stability and convergence rate.
• You can apply the initial conditions to the whole domain or zones of the
• On the other hand, unphysical initial conditions can slow down the convergence
domain.
rate or can cause divergence.
• You need to define boundary conditions and initials conditions for every single variable
you are solving.
• Setting the right boundary conditions is extremely important, but you need to
understand the physics.
• Minimize grid skewness, non-orthogonality, growth rate, and aspect ratio near the
boundaries. You do not want to introduce diffusion errors early in the simulation,
specially close to the inlets.
• You need to understand the physics in order to set the right boundary conditions.
910 911
Boundary conditions and initial conditions Boundary conditions and initial conditions
A few considerations and guidelines A few considerations and guidelines
• The required values of the boundary conditions and initial conditions depend on the • Do not force the flow at the outlet, use a zero normal gradient for all flow variables
equations you are solving and physical models used, e.g., except pressure. The solver extrapolates the required information from the interior.
• For incompressible and laminar flows you will need to set only the velocity and • Be careful with backward flow at the outlets (flow coming back to the domain) and
pressure. backward flow at inlets (reflection waves), they required special treatment.
• If you are solving a turbulent compressible flow you will need to set velocity, • If possible, select inflow and outflow boundary conditions such that the flow either goes
pressure, temperature and the turbulent variables. in or out normal to the boundaries.
• For multiphase flows you will need to set the primitives variables for each phase. • Use zero gradient boundary conditions only with incompressible flows and when you
You will also need to initialize the phases. are sure that the flow is fully developed.
• If you are doing turbulent combustion or chemical reactions, you will need to • Outlets that discharge to the atmosphere can use a static pressure boundary
define the species, reactions and primitive and turbulent variables. condition. This is interpreted as the static pressure of the environment into which the
• Minimize grid skewness, non-orthogonality, growth rate, and aspect ratio near the flow exhausts.
boundaries. You do not want to introduce diffusion errors early in the simulation, • Inlets that take flow into the domain from the atmosphere can use a total pressure
specially close to the inlets. boundary condition (e.g. open window).
• Try to avoid large gradients in the direction normal to the boundaries and near inlets • Mass flow inlets produce a uniform velocity profile at the inlet.
and outlets. That is to say, put your boundaries far away from where things are • Pressure specified boundary conditions allow a natural velocity profile to develop.
happening.
912 913
Boundary conditions and initial conditions Boundary conditions and initial conditions
• Inlets and outlets boundary conditions: • Zero gradient and backflow boundary conditions:
• Inlets are for regions where inflow is expected; however, inlets might support • Zero gradient boundary conditions extrapolates the values from the domain.
outflow when a velocity profile is specified. They require no information.
• Pressure boundary conditions do not allow outflow at the inlets. • Zero gradient boundary conditions can be used at inlets, outlets, and walls.
• Velocity specified inlets are intended for incompressible flows. • Backflow boundary conditions provide a generic outflow/inflow condition, with
• Pressure and mass flow inlets are suitable for compressible and incompressible specified inflow/outflow for the case of backflow.
flows. • In the case of a backflow outlet, when the flux is positive (out of domain) it
• Same concepts apply to outlets, which are regions where outflow is expected. applies a Neumann boundary condition (zero gradient), and when the flux is
negative (into of domain), it applies a Dirichlet boundary condition (fixed value).
• Same concept applies to backflow inlets.
914 915
Boundary conditions and initial conditions Boundary conditions and initial conditions
• On the outlet pressure boundary condition • On the outlet pressure boundary condition
• Some combinations of boundary conditions are very stable and some are less • If you only rely on a QOI and the residuals, you will not see any major difference
reliable. between the two cases with different outlet pressure boundary condition.
• And some configurations are unreliable. • This is very misleading.
• Inlet velocity at the inlet and pressure zero gradient at the outlet. This • However, when you visualize the solution you will realize that something is
combination should be avoided because the static pressure level is not wrong. This is a case where pretty pictures can be used to troubleshoot the
fixed. solution.
• Qualitatively speaking, the results are very different. • Quantitative speaking, the results are very similar.
• This simulation will eventually crash. • However, this simulation will eventually crash.
BCs 1. Inlet velocity and fixed outlet pressure BCs 2. Inlet velocity and zero gradient outlet pressure
www.wolfdynamics.com/wiki/BC/aniBC1.gif www.wolfdynamics.com/wiki/BC/aniBC2.gif
Residual plot for pressure Quantity of interest – Force coefficient on the body
916 917
Boundary conditions and initial conditions Boundary conditions and initial conditions
• Symmetry boundary conditions: • Location of the outlet boundary condition:
• Symmetry boundary conditions are a big simplification of the problem. However, • Place outlet boundary conditions as far as possible from recirculation zones or
they help to reduce mesh cell count. backflow conditions, by doing this you increase the stability.
• Have in mind that symmetry boundary conditions only apply to planar faces. • Remember, backflow conditions requires special treatment.
Far enough so the flow can be
• To use symmetry boundary conditions, both the geometry and the flow field must Possible backflow Might be OK
considered fully developed
be symmetric.
• Mathematically speaking, setting a symmetry boundary condition is equivalent
to: zero normal velocity at the symmetry plane, and zero normal gradients of all
variables at the symmetry plane.
• Physically speaking, they are equivalent to slip walls.
918 919
Boundary conditions and initial conditions Boundary conditions and initial conditions
• Domain dimensions (when the dimensions are not known): • OpenFOAM® distinguish between base type boundary conditions and primitive type
boundary conditions.
• 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).
• Always verify that there are no significant gradients normal to any of the boundaries patches. If there Base type boundary conditions Primitive type boundary conditions
are, you should consider increasing the domain dimensions.
• Base type boundary conditions are based on
geometry information (surface patches) or on inter- • Primitive type boundary condition assigns the value
processor communication link (halo boundaries). to the field variables in the given surface patch.
• Base type boundary conditions are defined in the • Primitive type boundary conditions are defined in
file boundary located in the directory the field variables dictionaries located in the
constant/polyMesh directory 0 (e.g. U, p).
• The file boundary is automatically created when • When we talk about primitive type boundary
you generate or convert the mesh. conditions we are referring to Dirichlet, Neumann or
• When you convert a mesh to OpenFOAM® format, Robin boundary conditions.
you might need to manually modify the file • You need to manually create the field variables
boundary. This is because the conversion utilities dictionaries (e.g. 0/U, 0/p, 0/T, 0/k, 0/omega).
do not recognize the boundary type of the original • Remember, if you forget to define a primitive
mesh. boundary condition, OpenFOAM® will complain and
• Remember, if a base type boundary condition is will tell you where and what is the error.
missing, OpenFOAM® will complain and will tell you • Also, if you misspelled something OpenFOAM® will
where and what is the error. complain and will tell you where and what is the
• Also, if you misspelled something OpenFOAM® will error.
complain and will tell you where and what is the
error
920 921
Boundary conditions and initial conditions Boundary conditions and initial conditions
• The following base type and primitive type boundary conditions are • The base type patch can be any of the boundary conditions available in
constrained or paired. OpenFOAM®.
• That is, the type needs to be same in the boundary dictionary and field • Mathematically speaking; they can be Dirichlet, Neumann or Robin
variables dictionaries (e.g. 0/U, 0/p, 0/T, 0/k, 0/omega). boundary conditions.
fixedValue
symmetry symmetry zeroGradient
symmetryPlane symmetryPlane inletOutlet
empty empty slip
patch
wedge wedge totalPressure
supersonicFreeStream
cyclic cyclic
and so on …
processor processor Refer to the doxygen documentation for a list of all numerical
boundary conditions available.
922 923
Boundary conditions and initial conditions Boundary conditions and initial conditions
• The wall base type boundary condition is defined as follows: • To deal with backflow at outlets, you can use the following boundary condition:
• This boundary condition is not contained in the patch base type boundary conditions
• The inletValue keyword is used for the reverse flow.
group, because specialize modeling options can be used on this boundary condition.
• In this case, if flow is coming back into the domain it will use the value set using the
• An example is turbulence modeling, where turbulence can be generated or
keyword inletValue. Otherwise it will use a zeroGradient boundary condition.
dissipated at the walls.
924 925
Boundary conditions and initial conditions Boundary conditions and initial conditions
• Typical boundary conditions are as follows (external aerodynamics), • Typical wall functions boundary conditions are as follows,
Boundary type description Pressure Velocity Turbulence fields Field variable Wall functions – High RE Resolved BL – Low RE
Boundary conditions and initial conditions Boundary conditions and initial conditions
• Finally, remember that the name of the base type boundary condition and the name • There are numerous primitive type boundary conditions implemented in
of the primitive type boundary condition needs to be the same, if not, OpenFOAM® OpenFOAM®.
will complain.
• You can find the source code of the numerical boundary conditions in the
• Pay attention to this, specially if you are converting the mesh from another format.
following directory:
• Also, do not use spaces of funny characters when assigning the names to the
boundary patches.
• The following names are consistent among all dictionary files,
• $WM_PROJECT_DIR/src/finiteVolume/fields
fixedWalls
{
type wall;
inGroups 1(wall);
nFaces 60;
fixedWalls
startFace 780;
fixedWalls
}
frontAndBack
{
Boundary conditions and type empty;
inGroups 1(empty);
functionObjects documentation nFaces 800;
startFace 840;
} frontAndBack
)
fixedWalls
930 931
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);
base type and name of the original format. If
nFaces 800; 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
932 933
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
doing, you do not need to change fixedWalls type and a name, they will be grouped as follows:
{ {
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; starting face and ending face of the startFace 780;
type empty;
} }
patch. inGroups 1(empty);
frontAndBack frontAndBack nFaces 800;
{ • This is created automatically when { startFace 840;
}
type empty; generating the mesh or converting type empty;
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.
934 935
Boundary conditions and initial conditions Boundary conditions and initial conditions
The 0/U dictionary The 0/p dictionary
• For a generic case, the primitive type BC are assigned as follows (U), • For a generic case, the primitive 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 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);
936 937
Roadmap
938 939
Tensor Rank Common name Basic class Access function can be declared in the following way
942 943
• The function cout will work fine, but it will give you problems when running in parallel. Determinant det T det(T)
944 You can find a complete list of all operators in the programmer’s guide 945
Programming in OpenFOAM®. Building blocks Programming in OpenFOAM®. Building blocks
Dimensional units in OpenFOAM® Dimensional units in OpenFOAM®
• As we already know, OpenFOAM® is fully dimensional. • Units are defined using the dimensionSet class tensor, with its units defined using
the dimensioned<Type> template class, the <Type> being scalar, vector, tensor,
• Dimensional checking is implemented as a safeguard against implementing etc. The dimensioned<Type> stores the variable name, the dimensions and the
a meaningless operation. tensor values.
• OpenFOAM® encourages the user to attach dimensional units to any tensor • For example, a tensor with dimensions is declare in the following way:
and it will perform dimension checking of any tensor operation.
• You can find the dimensional classes in the directory 1 dimensionedTensor sigma
2 (
$FOAM_SRC/OpenFOAM/dimensionedTypes/ 3 “sigma”,
4 dimensionSet(1, -1, -2, 0, 0, 0, 0),
• The dimensions can be hardwired directly in the source code or can be
5 tensor(10e6,0,0,0,10e6,0,0,0,10e6)
defined in the input dictionaries. 6 );
• From this point on, we will be attaching dimensions to all the tensors.
• The units of the class dimensionSet are defined as follows • To attach dimensions to any tensor, you need to access dimensional units class.
• To do so, just add the header file dimensionedTensor.H to your program.
dimensionSet (kg, m, s, K, mol, A, cd)
#include “dimensionedTensor.H”
...
...
• Therefore, the tensor sigma, ...
dimensionedTensor sigma
(
1 dimensionedTensor sigma "sigma",
dimensionSet(1, -1, -2, 0, 0, 0, 0),
2 (
tensor(1e6,0,0,0,1e6,0,0,0,1e6)
3 “sigma”, );
4 dimensionSet(1, -1, -2, 0, 0, 0, 0), Info<< "Sigma: " << sigma << endl;
5 tensor(10e6,0,0,0,10e6,0,0,0,10e6) ...
6 ); ...
...
• Has pressure units or • The output of the previous program should looks like this:
sigma sigma [1 -1 -2 0 0 0 0] (1e+06 0 0 0 1e+06 0 0 0 1e+06)
948 949
Programming in OpenFOAM®. Building blocks Programming in OpenFOAM®. Building blocks
Dimensional units examples OpenFOAM® lists and fields
• As for base tensors, you can access the information of dimensioned tensors. • OpenFOAM® frequently needs to store sets of data and perform mathematical
operations.
• For example, to access the name, dimensions, and values of a dimensioned tensor,
you can proceed as follows: • OpenFOAM® provides an array template class List<Type>, making it possible to
create a list of any object of class Type that inherits the functions of the Type. For
example a List of vector is List<vector>.
Info << “Sigma name: “ << sigma.name ( ) << endl;
Info << “Sigma dimensions: “ << sigma.dimensions ( ) << endl; • Lists of the tensor classes are defined in OpenFOAM® by the template class
Info << “Sigma value: “ << sigma.value ( ) << endl; Field<Type>.
• For better code legibility, all instances of Field<Type>, e.g. Field<vector>, are
renamed using typedef declarations as scalarField, vectorField, tensorField,
• To extract a value of a dimensioned tensor, you can proceed as follows:
symmTensorField, tensorThirdField and symmTensorThirdField.
• You can find the field classes in the directory
Info<< "Sigma yy (22) value: " << sigma.value().yy() << endl;
$FOAM_SRC/OpenFOAM/fields/Fields.
• Algebraic operations can be performed between fields, subject to obvious restrictions
• Note that the value() member function first converts the expression to a tensor, which such as the fields having the same number of elements.
has a yy() member function. • OpenFOAM® also supports operations between a field and a zero rank tensor, e.g.
• The dimensionedTensor class does not have a yy() member function, so it is not all values of a Field U can be multiplied by the scalar 2 by simple coding the
possible to directly get its value by using sigma.yy(). following line, U = 2.0 * U.
950 951
• At this point, we are a little bit familiar with tensor, fields, and lists in • The cells are contiguous, i.e., they do not overlap and completely fill the domain.
OpenFOAM®. • Dependent variables and other properties are stored at the cell centroid.
• They are the base to building applications in OpenFOAM®. • No limitations on the number of faces bounding each cell.
• Let us now take a look at the whole solution process: • No restriction on the alignment of each face.
• Creation of the tensors. • The mesh class polyMesh is used to construct the polyhedral mesh using the
• Mesh assembly. minimum information required.
• Fields creation. • You can find the polyMesh classes in the directory $FOAM_SRC/OpenFOAM/meshes
• Equation discretization. • The fvMesh class extends the polyMesh class to include additional data needed for
the FVM discretization.
• All by using OpenFOAM® classes and template classes
• You can find the fvMesh classes in the directory
$FOAM_SRC/src/finiteVolume/fvMesh
956 957
Programming in OpenFOAM®. Building blocks Programming in OpenFOAM®. Building blocks
Discretization of a tensor field in OpenFOAM® Data stored in the fvMesh class
• The template class geometricField relates a tensor
field to a fvMesh. Access
Class Description Symbol
• Using typedef declarations geometricField is renamed
function
to volField (cell center), surfaceField (cell faces), and volScalarField Cell volumes V()
pointField (cell vertices).
• You can find the geometricField classes in the directory surfaceVectorField Face area vector Sf()
$FOAM_SRC/OpenFOAM/fields/GeometricFields.
surfaceScalarField Face area magnitude magSf()
• The template class geometricField stores internal
fields, boundary fields, mesh information, dimensions, volVectorField Cell centres C()
old values and previous iteration values.
surfaceVectorField Face centres Cf()
• A geometricField inherits all the tensor algebra of its
corresponding field, has dimension checking, and can surfaceScalarField Face fluxes Phi()
be subjected to specific discretization procedures.
• Let us now access the mesh information of a simple
case.
958 959
• Remember, the PDEs or ODEs we want to solve involve derivatives of tensor fields
Sp(rho,phi)
with respect to time and space. What we re doing at this point, is applying the finite Source
SuSp(rho,phi)
volume classes to the fields, and assembling a linear system.
vol<type>Field scalar, volScalarField surfaceScalarField
962 963
fvm::ddt(T) - fvm::laplacian(DT,T)
+ fvm::div(phi,T) Discretize equations );
- fvm::laplacian(DT,T)
); Teqn.solve(); Solve the linear system Teqn
• Here, fvScalarMatrix contains the matrix derived from the discretization of the model
• Remember, you will need to first create the mesh, and initialize the variables and equation.
constants. That is, all the previous steps. • fvScalarMatrix is used for scalar fields and fvVectorMatrix is used for vector fields.
• Finally, everything we have done so far inherits all parallel directives. There is no • This syntax is more general, since it allows the easy addition of terms to the model
need for specific parallel programming. equations.
964 965
Programming in OpenFOAM®. Building blocks Programming in OpenFOAM®. Building blocks
Discretization of the basic PDE terms in OpenFOAM® Example of use of tensor and field classes
• At this point, OpenFOAM® assembles and solves the following linear system, • Let us study a fvMesh example. First let us compile the program my_Test-
mesh. Type in the terminal,
1. $> cd $PTOFC/programming_playground/my_mesh/
2. $> wmake
• At this point, take a look at the output and study the file Test-mesh.C. Try to
Coefficient Matrix (sparse, square) understand what we have done.
The coefficients depend on geometrical quantities, Boundary conditions
fluid properties and non linear equations and source terms • FYI, the original example is located in the directory
Unknow quantity
$PTOFC/programming_playground/test/mesh.
966 967
• You can access the API documentation in the following link, https://cpp.openfoam.org/v5/ 1. Programming in OpenFOAM®. Building blocks.
• You can access the coding style guide in the following link, https://openfoam.org/dev/coding-style-guide/
• You can report programming issues in the following link, https://bugs.openfoam.org/rules.php 2. codeStream – Highlights
• You can access openfoamwiki coding guide in the following link,
http://openfoamwiki.net/index.php/OpenFOAM_guide
3. Implementing boundary conditions using
• You can access the user guide in the following link, https://cfd.direct/openfoam/user-guide/ codeStream
• You can read the OpenFOAM® Programmer’s guide in the following link (it seems that this guide is not
supported anymore), http://foam.sourceforge.net/docs/Guides-a4/ProgrammersGuide.pdf 4. Solution initialization using codeStream
5. Implementing boundary conditions using high level
A few good C++ references programming
• The C++ Programming Language. B. Stroustrup. 2013, Addison-Wesley.
• The C++ Standard Library. N. Josuttis. 2012, Addison-Wesley. 6. Modifying applications – Highlights
• C++ for Engineers and Scientists. G. J. Bronson. 2012, Cengage Learning.
• Sams Teach Yourself C++ in One Hour a Day. J. Liberty, B. Jones. 2004, Sams Publishing. 7. Implementing an application from scratch
• C++ Primer. S. Lippman, J. Lajoie, B. Moo. 2012, Addison-Wesley.
• http://www.cplusplus.com/ 8. Adding the scalar transport equation to icoFoam
• http://www.learncpp.com/
• http://www.cprogramming.com/
• http://www.tutorialspoint.com/cplusplus/
• http://stackoverflow.com/
968 969
codeStream – Highlights codeStream – Highlights
• There are many boundary conditions available in OpenFOAM®. • When it comes to initial conditions, you can use the utility setFields.
• But from time to time it may happen that you do not find what you are looking for. • This utility is very flexible, you can even read STL files and use them to initialize fields.
• It is possible to implement your own boundary conditions, so in theory you can do whatever you • But again, it may happen that you can not get the desired results.
want.
• As for boundary conditions, to implement your own initials conditions you have three options:
• Remember, you have the source code. • Use codeStream.
• To implement your own boundary conditions, you have three options: • Use high level programing.
• Use codeStream.
• Use an external library (e.g., swak4foam).
• Use high level programing. • codeStream is the simplest way to implement initial conditions, and most of the times you will
• Use an external library (e.g., swak4foam). be able to code initial conditions with no problem.
• codeStream is the simplest way to implement boundary conditions, and most of the times you • If you can not implement your initial conditions using codeStream, you can use high level
will be able to code boundary conditions with no problem. programming. However, this requires some knowledge on C++ and OpenFOAM® API.
• If you can not implement your boundary conditions using codeStream, you can use high level • Hereafter, we are going to work only with codeStream.
programming. However, this requires some knowledge on C++ and OpenFOAM® API. • Using high level programming is a little bit more trickier, and we guarantee you that 99% of the
• Hereafter, we are going to work with codeStream and basic high level programming. time codeStream will work.
• We are not going to work with swak4Foam because it is an external library that is not officially • 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 relative easy to supported by the OpenFOAM foundation®. However, it works very well and is relative easy to
use. use.
970 971
972 973
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• OpenFOAM® includes the capability to compile, load and execute C++ code Body of the codeStream directive for boundary conditions
at run-time.
patch-name Patch name
• This capability is supported via the directive #codeStream, that can be used {
type fixedValue;
in any input file for run-time compilation. value #codeStream
Use codeStream to set the value
{ of the boundary condition
• This directive reads the entries code (compulsory), codeInclude (optional), codeInclude
#{
codeOptions (optional), and codeLibs (optional), and uses them to #include "fvCFD.H" Files needed for compilation
generate the dynamic code. #};
• The source code and binaries are automatically generated and copied in the codeOptions
#{
directory dynamicCode of the current case. -I$(LIB_SRC)/finiteVolume/lnInclude \ Compilation options
-I$(LIB_SRC)/meshTools/lnInclude
• The source code is compiled automatically at run-time. #};
codeLibs
• The use of codeStream is a very good alternative to avoid high level #{
Libraries needed for compilation.
Needed if you want to visualize the
programming of boundary conditions or the use of external libraries. -lmeshTools \
-lfiniteVolume output of the boundary condition
at time zero
• Hereafter we will use codeStream to implement new boundary conditions, #};
but have in mind that codeStream can be used in any dictionary. code
Insert your code here.
#{
At this point, you need to know
#}; how to access mesh information
};
}
974 975
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
• Let us implement a parabolic inlet profile. • We will use the following formula to implement the parabolic inlet profile
• The firs step is identifying the patch, its location and the dimensions.
• You can use paraview to get all visual references.
Outlet
pressure-outlet-7
• For this specific case c is the patch midpoint in the y direction (8), r is the patch
semi-height or radius (8) and Umax is the maximum velocity.
• We should get a parabolic profile similar to this one,
Inlet
velocity-inlet-5
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, Implementation of a parabolic inlet profile using codeStream
1 code Index used to access the • This case is ready to run, the input files are located in the directory
2 #{ y coordinate $PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet
3 ... 0→x
4 ...
5 ...
1→y • To run the case, type in the terminal,
6 const scalar pi = constant::mathematical::pi; 2→z
7 const scalar U_0 = 2.; //maximum velocity
8 const scalar p_ctr = 8.; //patch center 1. $> cd $PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet
9 const scalar p_r = 8.; //patch radius
10 2. $> foamCleanTutorials
11 forAll(U, i) //equivalent to for (int i=0; patch.size()<i; i++)
12
13
{
const scalar y = patch.Cf()[i][1];
3. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh
• In lines 6-17 we implement the new boundary condition. • The codeStream boundary condition is implemented in the file 0/U.
• In lines 6-9 we declare a few constant needed in our implementation.
• In lines 11-15 we use a forAll loop to access the boundary patch face centers and to assign the velocity profile
values. Notice the U was previously initialized.
• In line 13 we get the y coordinates of the patch faces center.
• In line 14 we assign the velocity value to the patch faces center.
• In line 17 we write the U values to the dictionary. 980 981
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codeStream codeStream works with scalar and vector fields
• If everything went fine, you should get something like this • We just implemented the input parabolic profile using a vector field.
• You can do the same using a scalar field, just proceed in a similar way.
• Remember, now we need to use scalars instead of vectors.
• And you will also use an input dictionary holding a scalar field.
1 code
2 #{
3 ...
4 ...
5 ...
6 scalarField S(patch.size(), scalar(0) ); Initialize scalar field
7
8 forAll(S, i) Loop using scalar field size
9 {
10 const scalar y = patch.Cf()[i][1];
11 S[i] = scalar( 2.0*sin(3.14159*y/8.) );
Write profile values
12 } in scalar field
13
14 S.writeEntry("", os);
Write output to input
15 #}; dictionary
Notice that the name of the field does not need to be the same as the name of the input dictionary
982 983
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a paraboloid inlet profile using codeStream Implementation of a paraboloid inlet profile using codeStream
• Let us work in a case a little bit more complicated, a paraboloid input profile. • We will implement the following equation in the boundary patch auto3.
• As usual, the first step is to get all the spatial references.
Inlet
auto3
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a paraboloid inlet profile using codeStream Implementation of a paraboloid 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/3Delbow_Uparaboloid/
• To run the case, type in the terminal,
1. $> cd $PTOFC/101programming/codeStream_BC/3Delbow_Uparaboloid/
2. $> foamCleanTutorials
3. $> gmshToFoam ../../../meshes_and_geometries/gmsh_elbow3d/geo.msh
988 989
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
codedFixedValue and codedMixed boundary conditions Body of the codedFixedValue boundary conditions
• OpenFOAM® also includes the boundary conditions codedFixedValue and patch-name Patch name
codedMixed. {
Use codedFixedValue and
type codedFixedValue;
• These boundary conditions are derived from codeStream and work in a value uniform (0 0 0); initializations
• Another feature of these boundary conditions, is that the code section can be codeInclude
#{
read from an external dictionary (system/codeDict), which is run-time #include "fvCFD.H"
Files needed for compilation
modifiable. #include <cmath>
#include <iostream>
#};
• The boundary condition codedMixed works in similar way. This boundary In this section we do the actual
implementation of the boundary
condition gives you access to fixed values (Dirichlet BC) and gradients code
#{ condition.
(Neumann BC). This is the only part of the body
#}; that you will need to change. The
• Let us implement the parabolic profile using codedFixedValue. } rest of the body is a template that
990
you can always reuse. 991
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, codedFixedValue and codedMixed boundary conditions
• As you can see, the syntax and use of the codedFixedValue and codedMixed
1 code
2 #{ boundary conditions is much simpler than codeStream.
3 const fvPatch& boundaryPatch = patch();
4 const vectorField& Cf = boundaryPatch.Cf(); • You can use these instructions as a template. At the end of the day, you only need to
5
6
vectorField& field = *this; modify the code section.
7 scalar U_0 = 2, p_ctr = 8, p_r = 8;
8
• Depending of what you want to do, you might need to add new headers and
9 forAll(Cf, faceI) compilation options.
10 {
11 field[faceI] = vector(U_0*(1-(pow(Cf[faceI].y()-p_ctr,2))/(p_r*p_r)),0,0); • Remember, is you are working with a vector, you need to use vector fields. Whereas,
12 }
13 #};
if you are working with scalars, you need to use scalars fields.
• One disadvantage of these boundary conditions, is that you can not visualize the
fields at time zero. You will need to run the simulation for at least one iteration.
• Lines 3-5, are always standard, they give us access to mesh and field information in the patch.
• The coordinates of the faces center are stored in the vector field Cf (line 4). • On the positive side, accessing time and other values from the simulation database is
• In this case, as we are going to implement a vector profile, we initialize a vector field where we are going to straightforward.
assign the profile (line 5).
• Time can be accessed by adding the following statement,
• In line 7 we initialize a few constants that will be used in our implementation.
• In lines 9-12 we use a forAll loop to access the boundary patch face centers and to assign the velocity profile
values. this->db().time().value()
• In line 11 we do the actual implementation of the boundary profile (similar to the codeStream case). The
vector field was initialize in line 5.
992 993
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• Let us add time dependency to the parabolic profile. Implementation of a parabolic inlet profile using codedFixedValue
• This case is ready to run, the input files are located in the directory
1 code $PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet_timeDep
2 #{
3 const fvPatch& boundaryPatch = patch(); • To run the case, type in the terminal,
4 const vectorField& Cf = boundaryPatch.Cf();
5 vectorField& field = *this;
6
7 scalar U_0 = 2, p_ctr = 8, p_r = 8; 1. $> cd $PTOFC/101programming/codeStream_BC/2Delbow_UparabolicInlet_timeDep
8
9 scalar t = this->db().time().value(); Time 2. $> foamCleanTutorials
10
11 forAll(Cf, faceI) 3. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh
12 {
13 field[faceI] = vector(sin(t)*U_0*(1-(pow(Cf[faceI].y()-p_ctr,2))/(p_r*p_r))),0,0);
4. $> icoFoam | tee log
14 }
15 #};
Time dependency 5. $> paraFoam
• This implementation is similar to the previous one, we will only address how to deal with time.
• The codeStream boundary condition is implemented in the file 0/U.
• 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.
• In this case, we added time dependency by simple multiplying the parabolic profile by the
function sin(t).
994 995
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
Implementation of a parabolic inlet profile using codedFixedValue Filling a tank using codedFixedValue
• If everything went fine, you should get something like this • Let us do a final example.
• 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
996 997
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• Definition of the vector field boundary condition (dictionary file U), • Definition of the vector field boundary condition (dictionary file U),
Name of the patch where we want to implement the boundary condition 7 code Code section. The actual implementation of the BC is done in this section
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 0 0); 20 forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++)
5 redirectType inletProfile1; 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 Use conditional structure to
25 (Cf[faceI].z() < maxz) &&
10 const vectorField& Cf = boundaryPatch.Cf(); information and initialize 26 (Cf[faceI].y() > miny) && select faces according to the
11 vectorField& field = *this; vector field field 27 (Cf[faceI].y() < maxy) variables defined in lines 13-16
12 28 )
13 scalar minz = 0.4; 29 {
14 scalar maxz = 0.6; 30 if ( t < 1.)
15 scalar miny = 0.5; Initialize variables 31 { Use conditional structure to
16 scalar maxy = 0.7; 32 field[faceI] = vector(1,0,0); add time dependency and
17 33 } assign values to the
18 scalar t = this->db().time().value(); Access time 34 else
... selected faces.
35 {
... 36 field[faceI] = vector(0,0,0); The variable field was
... 37 } initialize in line 11.
40 #}; 38 }
41 } 39 }
40 #};
41 }
998 999
Implementing boundary conditions using codeStream Implementing boundary conditions using codeStream
• Definition of the scalar field boundary condition (dictionary file alpha.water), • Definition of the scalar field boundary condition (dictionary file alpha.water),
Name of the patch where we want to implement the boundary condition 7 code Code section. The actual implementation of the BC is done in this section
8 #{
1 leftWall Use codedFixedValue BC and initialize value. ...
2 { Loop using size of boundary patch (Cf) and iterator
The initialization is only needed for paraview ...
3 type codedFixedValue; in order to visualize something at time zero. ... faceI.
4 value uniform 0; 22 This is equivalent to:
5 redirectType inletProfile2; Unique name of the BC 23 forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++)
6 Do not use the same name in other patches 24 {
7 code 25 if (
8 #{ 26 (Cf[faceI].z() > minz) && Use conditional structure to
9 const fvPatch& boundaryPatch = patch(); Access boundary mesh 27 (Cf[faceI].z() < maxz) && select faces according to the
Code section. The actual implementation of
10 const vectorField& Cf = boundaryPatch.Cf(); information and initialize 28 (Cf[faceI].y() > miny) &&
11 scalarField& field = *this; variables defined in lines 13-16
scalar field field 29 (Cf[faceI].y() < maxy)
12 30 )
13 field = patchInternalField(); Assign value from the internal field to the patch 31 {
14
the BC is done in this section
32 if ( t < 1.)
15 scalar minz = 0.4; 33 {
16 scalar maxz = 0.6;
Use conditional structure to add
Initialize variables 34 field[faceI] = 1.; time dependency and assign
17 scalar miny = 0.5; 35 }
18 scalar maxy = 0.7; 36 else
values to the selected faces.
20 37 { The variable field was initialize in
21 scalar t = this->db().time().value(); Access time 38 field[faceI] = 0.; line 11.
22 39 }
... 40 }
... 41 }
... 42 #};
42 #}; 43 }
43 }
1000 1001
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/fillBox_BC/
• To run the case, type in the terminal,
1. $> cd $PTOFC/101programming/codeStream_BC/fillBox_BC/
2. $> foamCleanTutorials
3. $> blockMesh
4. $> decomposePar
5. $> mpirun -np 4 interFoam -parallel | tee log
6. $> reconstructPar
7. $> paraFoam
1004 1005
Solution initialization using codeStream Solution initialization using codeStream
Body of the codeStream directive for initial conditions Implementation of an elliptic initialization using codeStream
internalField #codeStream Use codeStream to set the value • Let us implement an elliptic initialization using codeStream.
{ of the initial conditions
{
• The firs step is to know your domain and identify the region that you want to initialize.
codeInclude
#{
• Then you will need to do a little bit of math to get the expression for the initialization.
#include "fvCFD.H" Files needed for compilation
• In this example, we are also going to show you how to do the same initialization by
Initial conditions
#};
reading a STL file with the utility setFields.
codeOptions
codeLibs
Libraries needed for compilation.
#{
-lmeshTools \ Needed if you want to visualize the
-lfiniteVolume output of the initial conditions at
#}; time zero
code Phase 1
#{
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
1006 1007
-lmeshTools \
-lfiniteVolume
if ( pow(y-ke,2) <= ((1 - pow(x-he,2)/pow(ae,2) )*pow(be,2)) )
following statement
#{
Insert your code here. }
alpha.writeEntry("", os);
#}; At this point, you need to know
#};
}; how to access internal mesh
} information Write output to input dictionary
1008 1009
Solution initialization using codeStream Solution initialization using codeStream
Implementation of an elliptic initialization using codeStream Implementation of an elliptic initialization 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_INIT/elliptical_IC
• To run the case, type in the terminal,
1. $> cd $PTOFC/101programming/codeStream_INIT/elliptical_IC
2. $> foamCleanTutorials
3. $> blockMesh
4. $> rm –rf 0
5. $> cp –r 0_org 0
6. $> paraFoam
7. $> interFoam | tee log
8. $> paraFoam
codeStream initialization setFields initialization
Visualization of volume fraction (alpha.phase1) Visualization of volume fraction (alpha.phase1)
• In step 6, we launch paraFoam to visualize the initialization. www.wolfdynamics.com/wiki/BCIC/bubble_zeroG.gif www.wolfdynamics.com/wiki/BCIC/bubble_zeroG_SF.gif
1014 1015
{
const scalar x = mesh.C()[i][0];
const scalar y = mesh.C()[i][1];
Access cell centers coordinates 2. $> foamCleanTutorials
if (y >= -0.05*cos(2*constant::mathematical::pi*x)) 3. $> blockMesh
{
alpha[i] = 1.; 4. $> interFoam | tee log
}
} 5. $> paraFoam
alpha.writeEntry("", os);
#}; Write output to input dictionary
1016 1017
Solution initialization using codeStream Solution initialization using codeStream
Rayleigh-Taylor instability initialization Filling a tank using codeStream and codedFixedValue
• If everything went fine, you should get something like this • Let us do a final example.
• We will implement BCs and ICs at the same.
• For simplicity, we will only show the code section of the input files.
• This setup is similar to the last example of the previous section (filling a tank using
codedFixedValue).
1018 1019
Use codeStream to set the Name of the patch where we want to implement the boundary condition
internalField #codeStream
{ value of the initial conditions
1020 1021
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 alpha.water is as follows,
code Code section. The actual implementation of the BC is done here Name of the patch where we want to implement the boundary condition
#{
... 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; in order to visualize something at time zero.
This is equivalent to: value uniform 0;
forAll(Cf, faceI) for (int faceI=0; Cf.size()<faceI; faceI++) Unique name of the BC
{ 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) && const fvPatch& boundaryPatch = patch(); Access boundary mesh
select faces.
(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] = vector(1,0,0); Use conditional structure to
} scalar min = 0.5;
add time dependency and scalar max = 0.7;
Initialize variables
else
assign values to the
{
field[faceI] = vector(0,0,0); selected faces. scalar t = this->db().time().value(); Access time
} ...
} ...
} ...
#}; #};
}
1022 1023
1024 1025
Roadmap Implementing boundary conditions using high level programming
• Hereafter we will work with high level programming, this is the hard part of
1. Programming in OpenFOAM®. Building blocks. programming in OpenFOAM®.
2. codeStream – Highlights • High level programming requires some knowledge on C++ and OpenFOAM®
API library.
3. Implementing boundary conditions using • Before doing high level programming, we highly recommend you to try with
codeStream codeStream, most of the time it will work.
4. Solution initialization using codeStream • We will implement the parabolic profile, so you can compare this
implementation with codeStream ad codedFixedValue BCs.
5. Implementing boundary conditions using high level
programming • When we program boundary conditions, we are actually building a new
library that can be linked with any solver. To compile the library, we use the
6. Modifying applications – Highlights command wmake (distributed with OpenFOAM®).
7. Implementing an application from scratch • At this point, you can work in any directory. But we recommend you to work
in your OpenFOAM® user directory, type in the terminal,
8. Adding the scalar transport equation to icoFoam
1. $> cd $WM_PROJECT_USER_DIR/run
1026 1027
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
• Let us create the basic structure to write the new boundary condition, type in Directory structure of the new boundary condition
the terminal,
./myParabolicVelocity
├── Make
1. $> foamNewBC –f –v myParabolicVelocity │ ├── files
│ └── options
2. $> cd myParabolicVelocity
├── myParabolicVelocityFvPatchVectorField.C
└── myParabolicVelocityFvPatchVectorField.H
• The utility foamNewBC, will create the directory structure and all the files needed to
write your own boundary conditions. The directory contains the source code of the boundary condition.
• myParabolicVelocityFvPatchVectorField.C: is the actual source code of the
• We are setting the structure for a fixed (the option –f) velocity (the option –v), application. This file contains the definition of the classes and functions.
boundary condition, and we name our boundary condition ParabolicVelocity .
• myParabolicVelocityFvPatchVectorField.H: header files required to compile the
• If you want to get more information on how to use foamNewBC, type in the terminal, application. This file contains variables, functions and classes declarations.
• The Make directory contains compilation instructions.
1. $> foamNewBC –help • Make/files: names all the source files (.C), it specifies the boundary condition
library name and location of the output file.
• Make/options: specifies directories to search for include files and libraries to link the
solver against.
1028 1029
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
• Using this line as your reference location in the source code, follow these steps,
• Let us compile the library to see what errors we get. Type in the terminal, • Erase the following lines in incremental order (be sure to erase only the lines that
contain the words fieldData, timeVsData, wordData, labelData and boolData):
1. $> wmake 48-52, 64-68, 92-96, 105-109, 119-123, 177-180.
• Erase the following lines (they contain the word fieldData), 131, 146, 159-161.
• You will get a lot of errors. • Replace all the occurrences of the word scalarData with maxValue (11
• Since we deleted the datatypes fieldData, timeVsData, wordData, labelData and occurrences).
boolData in the header file, we need to delete them as well in the C file. Otherwise
the compiler complains. 1032 1033
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
1034 1035
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
164 fixedValueFvPatchVectorField::operator==
used to assign the values to the • In our implementation we do not use all the classes, we only use the first two classes.
boundary patches
165 ( • The first class is related to the initialization of the variables.
166 n_*maxValue_*(1.0 - sqr(coord)) Our boundary condition
167 ); • The second class is related to reading the input dictionaries.
168
• We will not comment on the other classes as it is out of the scope of this example
(they deal with input tables, mapping, and things like that).
• At this point we have a valid library where we implemented a new BC. • The implementation of the boundary condition is always done using the
• Try to compile it, we should not get any error (maybe one warning). Type in the updateCoeffs() member function.
terminal, • When we compile the source code, it will compile a library with the name specified in
the file Make/file. In this case, the name of the library is libmyParabolicVelocity.
1. $> wmake • The library will be located in the directory $(FOAM_USER_LIBBIN), as specified in
the file Make/file.
• If you are feeling lazy or you can not fix the compilation errors, you will find the source
code in the directory,
• $PTOFC/101programming/src/myParabolicVelocity
1036 1037
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
1038 1039
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
66
• At this point we have a valid library that can be linked with any solver.
Add these statements
1040 1041
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
1. $> cd $PTOFC/101programming/cases/elbow2d
• Open the file 0/U, and look for the definition of the new BC velocity-inlet-5,
velocity-inlet-5
{
type myParabolicVelocity; Name of the boundary condition
maxValue 2.0;
n (1 0 0); User defined values
y (0 1 0); max value, n, y
} If you set n or y to (0 0 0), the solver will
abort execution
1042 1043
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
1. $> foamCleanTutorials
15 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 2. $> fluentMeshToFoam ../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh
16
17 libs ("libmyParabolicVelocity.so"); Name of the library 3. $> icoFoam | tee log
18 You can add as many libraries as you like
19 application icoFoam; 4. $> paraFoam
1044 1045
Implementing boundary conditions using high level programming Implementing boundary conditions using high level programming
• Recompile, rerun the simulation, look at the output, and do the math.
1046 1047
1048 1049
Roadmap Implementing an application from scratch
• Let us do a little bit of high level programming, this is the hard part of working
1. Programming in OpenFOAM®. Building blocks. with OpenFOAM®.
2. codeStream – Highlights • At this point, you can work in any directory. But we recommend you to work
in your OpenFOAM® user directory, type in the terminal,
3. Implementing boundary conditions using
codeStream 1. $> cd $WM_PROJECT_USER_DIR/run
4. Solution initialization using codeStream • To create the basic structure of a new application, type in the terminal,
5. Implementing boundary conditions using high level
1. $> foamNewApp scratchFoam
programming
2. $> cd scratchFoam
6. Modifying applications – Highlights
7. Implementing an application from scratch • The utility foamNewApp, will create the directory structure and all the files needed to
create the new application from scratch. The name of the application is
8. Adding the scalar transport equation to icoFoam scratchFoam.
• If you want to get more information on how to use foamNewApp, type in the terminal,
73 } At this point we are outside of the time loop 1 Info<< "Reading field T\n" << endl;
74 2
75 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 3 volScalarField T Create scalar field T
76 4 (
77 Info<< nl << "ExecutionTime = " << runTime.elapsedCpuTime() << " s" 5 IOobject Create object for input/output operations
78 << " ClockTime = " << runTime.elapsedClockTime() << " s" 6 (
79 << nl << endl; 7 "T", Name of the dictionary file to read/write
80 8 runTime.timeName(), runtime directory
81 Info<< "End\n" << endl; Output this message 9 mesh, Object registry
82 10 IOobject::MUST_READ,
11 IOobject::AUTO_WRITE Read the dictionary in the runtime directory
83 return 0; End of the program (exit status). 12 ), (MUST_READ, and write the value in the runtime
84 } If everything went fine, the program should return 0. 13 mesh Link object to mesh directory (AUTO_WRITE).
85 To now the return value, type in the terminal, 14 ); If you do not want to write the value, use the option
86 $> echo $? NO_WRITE
1056 1057
Implementing an application from scratch Implementing an application from scratch
• Remember, in the file createFields.H, we declare all the variables (or fields) that • We also need to declare the constant DT, that is read from the dictionary
we will use (U and T in this case). transportProperties.
• The dimensions of the fields are defined in the input dictionaries, you also have the • The dimensions are defined in the input dictionary.
option to define the dimensions in the source code.
• You can also define the fields directly in the source file scratchFoam.C, but it is 33 Info<< "Reading transportProperties\n" << endl;
34
good practice to do it in the header. This improves code readability. 35 IOdictionary transportProperties Create object transportProperties used to
36 ( read data
37 IOobject
38 ( Name of the input dictionary
17 Info<< "Reading field U\n" << endl; 39 "transportProperties",
40 runTime.constant(), Location of the input dictionary, in this case
18 is located in the directory constant
19 volVectorField U Create vector field U 41 mesh,
20 ( 42 IOobject::MUST_READ_IF_MODIFIED, Re-read data if it is modified
21 IOobject 43 IOobject::NO_WRITE
22 ( 44 ) Do not write anything in the dictionary
23 "U", Name of the dictionary file to read/write 45 );
24 runTime.timeName(), 46
25 mesh, 47
26 IOobject::MUST_READ, 48 Info<< "Reading diffusivity DT\n" << endl;
27 IOobject::AUTO_WRITE 49
28 ), 50 dimensionedScalar DT Create scalar DT (diffusion coefficient)
29 mesh 51 (
52 transportProperties.lookup("DT") Access value of DT in the object
30 );
53 ); transportProperties
31
54
55 #include "createPhi.H" Creates and initializes the relative face-
56 flux field phi.
1058 1059
• $PTOFC/101programming/applications/solvers/scratchFoam
16
17 forAll(T, i) We add the initialization of T after the its declaration
18 {
19 const scalar x = mesh.C()[i][0];
• You will find a case ready to run in the directory, 20 const scalar y = mesh.C()[i][1]; Access cell center coordinates.
21 const scalar z = mesh.C()[i][2]; In this case y and z coordinates are not used.
22
$PTOFC/101programming/applications/solvers/scratchFoam/test_case 23 if ( 0.3 < x && x < 0.7) Conditional structure
24 {
25 T[i] = 1.;
26 }
• At this point, we are all familiar with the convection-diffusion equation and 27 }
28 T.write(); Write field T. As the file createFields.H is outside the time loop
OpenFOAM®, so you know how to run the case. Do your magic. the value is saved in the time directory 0
1060 1061
Implementing an application from scratch Implementing an application from scratch
• Let us compute a few extra fields. We are going to compute the gradient, divergence, • Let us talk about the file write.H,
and Laplacian of T.
• We are going to compute these fields in a explicit way, that is, after finding the 1
2
volVectorField gradT(fvc::grad(T)); Compute gradient of T.
fvc is the explicit operator, it will compute the
solution of T. 3 volVectorField gradT_vector
requested value using the solution of T
4 (
• Therefore we are going to use the operator fvc. 5 IOobject
6 (
• Add the following statements to the source code of the solver (scratchFoam.C), 7 "gradT",
8 runTime.timeName(), Save vector field in output dictionary gradT
9 mesh,
10 IOobject::NO_READ,
11 IOobject::AUTO_WRITE
68 } 12 ),
13 gradT
69 14 );
70 #include "continuityErrs.H" 15
71 #include "write.H" Add this header file ...
56
72 runTime.write(); 57 volScalarField divGradT
73 The file is located in the directory 58 (
74 } $PTOFC/101programming/applications/solvers/scratchFoam 59 IOobject
60 (
Compute divergence of gradT.
In this file we declare and define the new variables, take a look at it
61 "divGradT", The output of this operation is a scalar field.
62 runTime.timeName(), In this case we compute the quantity inside the scalar field
63 mesh, declaration (line 67).
64 IOobject::NO_READ, We use the fvc operator because the solution of gradT is
already known.
• Recompile the solver and rerun the test case. 65
66 ),
IOobject::AUTO_WRITE
• The solver will complain, try to figure out what is the problem (you are missing some 67
68 );
fvc::div(gradT)
In the dictionary fvSchemes, you will need to tell the solver how to do
information in the fvSchemes dictionary). 69 ... the interpolation of the term div(grad(T))
1062 1063
1064 1065
Adding the scalar transport equation to icoFoam Adding the scalar transport equation to icoFoam
• Open the file icoFoam.C using your favorite editor and add the new • Open the file createFields.H using your favorite editor and add the following lines
equation in lines 115-120, at the beginning of the file,
1 Info<< "Reading field S1 (passive scalar 1)\n" << endl;
2 volScalarField S1
111 U = HbyA - rAU*fvc::grad(p); 3 (
112 U.correctBoundaryConditions(); 4 IOobject
5 ( Declaration of scalar field S1.
113 } 6 "S1", The solver will read the input file S1
114 7 runTime.timeName(), (BC and IC).
8 mesh,
115 solve 9 IOobject::MUST_READ, You will need to create the file S1 in
116 ( Scalar transport equation. 10 IOobject::AUTO_WRITE the time directory 0.
117 fvm::ddt(S1) The name of the scalar is S1. 11 ),
We need to declare it in the 12 mesh
118 + fvm::div(phi, S1) 13 );
createFields.H file.
119 - fvm::laplacian(DT, S1) . We also need to read the coefficient DT.
14
15 Info<< "Reading diffusionProperties\n" << endl;
120 ); 16
121 17 IOdictionary diffusionProperties
122 runTime.write(); 18 (
19 IOobject Declaration of input/output dictionary
123 20 ( file.
21 "diffusionProperties", The name of the dictionary is
22 runTime.constant(), diffusionProperties and is located in
23 mesh,
24 IOobject::MUST_READ_IF_MODIFIED,
the directory constant.
• As the passive scalar equation depends on the vector field U, we need to 25 IOobject::NO_WRITE
26 )
add this equation after solving U. 27 );
28
29 Info<< "Reading diffusivity DT\n" << endl;
30 dimensionedScalar DT
31 (
Read DT value from the dictionary
32 diffusionProperties.lookup("DT") diffusionProperties.
1066 33 ); 1067
Adding the scalar transport equation to icoFoam Adding the scalar transport equation to icoFoam
• Those are all the modifications we need to do. • At this point we are ready to compile, type in the terminal,
• But before compiling the new solver, we need to modify the compilation
instructions. 1. $> wmake
• If you are feeling lazy or you can not fix the compilation errors, you will find the source
1 icoFoam.C code in the directory,
2
3 EXE = $(FOAM_APPBIN)/icoFoam
• $PTOFC/101programming/applications/solvers/my_icoFoam
Modified file
• You will find a case ready to run in the directory,
Name of the executable.
1 icoFoam.C Name of the input file To avoid conflicts with the original
installation, we give a different $PTOFC/101programming/applications/solvers/my_icoFoam/test_case
2 name to the executable
3 EXE = $(FOAM_USER_APPBIN)/my_icoFoam
Location of the executable.
To avoid conflicts with the original installation, we install the
executable in the user’s personal directory
1068 1069
Adding the scalar transport equation to icoFoam Adding the scalar transport equation to icoFoam
Running the case Running the case
• 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/applications/solvers/my_icoFoam/test_case
• To run the case, type in the terminal,
1. $> foamCleanTutorials
2. $> fluentMeshToFoam ../../../../../meshes_and_geometries/fluent_elbow2d_1/ascii.msh
S1 = 300
3. $> my_icoFoam | tee log
4. $> paraFoam
• Remember, you will need to create the file 0/S1 (boundary conditions and initial
conditions for the new scalar).
S1 = 350
S1 = 400
• You will also need to create the input dictionary constant/diffusionProperties,
from this dictionary we will read the diffusion coefficient value.
S1 inlet values Visualization of velocity magnitude and passive scalar S1
• Finally, remember to update the files system/fvSchemes and www.wolfdynamics.com/wiki/BCIC/2delbow_S1
What is turbulence?
A crash introduction to: • For the purpose of this training, let us state the following:
1. Turbulence modeling in OpenFOAM® • Turbulence is an unsteady, aperiodic motion in which all three velocity
components fluctuate in space and time.
2. Multiphase flows modeling in
• Every transported quantity shows similar fluctuations (pressure,
OpenFOAM® temperature, species, concentration, and so on)
3. Compressible flows in OpenFOAM® • Turbulent flows contains a wide range of eddy sizes (scales):
• Large eddies derives their energy from the mean flow. The size and
4. Moving bodies in OpenFOAM® velocity of large eddies are on the order of the mean flow.
5. Source terms in OpenFOAM® • Large eddies are unstable and they break-up into smaller eddies.
6. Scalar transport pluggable solver • The smallest eddies convert kinetic energy into thermal energy via
viscous dissipation.
• The behavior of small eddies is more universal in nature.
1074 1075
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
Von Karman vortices created when prevailing winds sweeping east across Flow around an airfoil with a leading-edge slat
the northern Pacific Ocean encountered Alaska's Aleutian Islands Photo credit: S. Makiya et al.
Buoyant plume of smoke rising from a stick of incense Photo credit: USGS EROS Data Center Satellite Systems Branch. Copyright on the images is held by the contributors. Apart from Fair Use,
Photo credit: https://www.flickr.com/photos/jlhopgood/ Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose.
This work is licensed under a Creative Commons License (CC BY-NC-ND 2.0) 1076 permission must be sought for any other purpose. 1077
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
Vortices on a 1/48-scale model of an F/A-18 aircraft inside a Water Tunnel Flow around two spheres. Left image: smooth sphere. Right image: sphere with rough surface at the nose
Photo credit: NASA Dryden Flow Visualization Facility. http://www.nasa.gov/centers/armstrong/multimedia/imagegallery/FVF Photo credit: http://www.mhhe.com/engcs/civil/finnemore/graphics/photos/AuthorRecommendedImages/index.html
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose. 1078 Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose 1079
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
URANS (K-Omega SST with no wall functions) – LES (Smagorinsky) – Vortices visualized by Q-criterion
Vortices visualized by Q-criterion www.wolfdynamics.com/wiki/squarecil/les.gif
www.wolfdynamics.com/wiki/squarecil/urans2.gif
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
• Simulating turbulent flows in any general CFD solver requires selecting a • Therefore, in order to accurately model/resolve turbulent flows, the
turbulence model, providing initial conditions and boundary conditions for the simulations must be three-dimensional, time-accurate, and with fine enough
closure equations of the turbulent model, selecting a near-wall modeling, meshes such that all spatial scales are resolved.
and choosing runtime parameters and numerics.
1084 1085
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
Reynolds number and Rayleigh number Reynolds number and Rayleigh number
• It is well known that the Reynolds number characterizes if the flow is laminar or turbulent. • If you are dealing with natural convection, you can use the Rayleigh number, Grashof number,
• So before doing a simulation or experiment, check if the flow is turbulent. and Prandtl number to characterize the flow.
• The Reynolds number is defined as follows,
Specific heat Thermal expansion coefficient
Buoyancy effects
Convective effects
Viscous effects Thermal conductivity
where
Viscous effects
Momentum diffusivity
• Where U and L are representative velocity and length scales.
Thermal diffusivity
1086 1087
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, C reeping flow (no s eparation)
S teady flow Re < 5
Along a surface (slender body) Easy to simulate
A pair of s table vortices
• If you are dealing with natural convection and buoyancy, turbulent flows occurs when Challenging to
Turbulent vortex s treet, but the
simulate
6
wake is narrower than in the
laminar cas e 3 x 10 > Re
Uns teady flow
Vorticity does not always mean turbulence Turbulence modeling – Fluctuations of transported quantities
• The Reynold number in this case is 100, for these conditions the flow still is laminar. • We have defined turbulence as an unsteady, aperiodic motion in which velocity components and
• We are in the presence of the Von Karman vortex street, which is the periodic shedding of vortices caused by every transported quantity fluctuate in space and time.
the unsteady separation of the fluid around blunt bodies. • For most engineering application it is impractical to account for all these instantaneous
• Vorticity is not a direct indication of turbulence. fluctuations.
• However turbulent flows are rotational, they exhibit vortical structures. 1090 • Therefore, we need to somehow remove those small scales by using models. 1091
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 in a pipe Turbulent flow in a pipe Averaged turbulent flow Instantaneous turbulent flow
• Turbulence has a direct effect on the velocity profiles and mixing of transported quantities. • In the left figure, the velocity profile has been averaged.
• The turbulent case shows two regions. One thin region close to the walls with very large velocity • In reality, the velocity profile fluctuates in time (right figure).
gradients, and a region far from the wall where the velocity profile is nearly uniform. • The thin region close to the walls has very large velocity gradients and is laminar.
• In the illustration, the velocity profile of the turbulent case has been averaged (in reality there are • Far from the flows, the flow becomes turbulent.
fluctuations). 1092 1093
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
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
exaggerated for clarity
• Near walls, in the boundary layer, the velocity changes rapidly. • Near walls, in the boundary layer, the velocity changes rapidly.
• In CFD, the most important zones are the viscous sublayer and the log-law layer. • The use of the non-dimensional velocity u+ and non-dimensional distance from the wall y+, results in a
• The buffer layer is the transition layer which we try to avoid. predictable boundary layer profile for a wide range of flows
• Turbulence models require different considerations depending on whether you solve the viscous sublayer, • Turbulence models require different considerations depending on whether you solve the viscous sublayer of
model the log-law layer, or solve the whole boundary layer. model the log-law layer.
1096 1097
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
Turbulence near the wall - Law of the wall Near-wall treatment and wall functions
• When dealing with wall turbulence, we need to
choose a near-wall treatment.
• If you want to resolve the boundary layer up to the
viscous sub-layer you need very fine meshes close
to the wall.
• In terms of y+, you need to cluster at least 6 to 10
layers at y+ < 10.
• This is the most accurate approach but it is
computationally expensive.
1098 1099
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
Cell size
This cell is resolving the eddies
• Turbulence modelling aims at predicting velocity and transported quantities fluctuations • To remove the instantaneous fluctuations or small scales, two methods can be used:
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.
• Reynolds averaging
• Therefore, if we want to capture all scales we need very fine meshes in the whole domain. • Filtering
• Both methods introduce additional terms that must be modeled for closure.
Bullet at Mach 1.5
Photo credit: Andrew Davidhazy. Rochester Institute of Technology. • We are going to talk about closure methods later.
Copyright on the images is held by the contributors. Apart from Fair Use, permission must be sought for any other purpose. 1100 1101
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
MODEL
URANS
RANS/URANS DES/LES DNS
complexity
Unsteady Reynolds-Averaged Navier-Stokes equations
SAS •
•
Solve the time-average NSE.
All turbulent spatial scales are
•
•
Solve the filtered unsteady NSE.
Sub-grid scales (SGS) are filtered,
•
•
Solves the unsteady laminar NSE.
Solves all spatial and temporal
Scale Adaptive Simulations
modeled. grid scales (GS) are resolved. scales; hence, requires extremely
Scale-Resolving Simulations
equation models, two equation hence requires small time-steps. • No modeling is required.
Detached Eddy Simulations models, Reynolds stress models,
• For most industrial applications, it is • It is extremely computational
transition models, and so on.
LES • This is the most widely approach for
computational expensive. However,
thanks to the current advances in
•
expensive.
Not practical for industrial flows.
Large Eddy Simulations industrial flows. parallel and scientific computing it is
becoming affordable. • It is intrinsically 3D and asymmetric.
• Unsteady RANS (URANS), use the
DNS same equations as the RANS but
with the transient term retained.
• Many models are available.
Direct Numerical Simulations • It is intrinsically 3D and asymmetric.
1102 • It can be used in 2D and 3D cases. 1103
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
Short description of some RANS turbulence models Turbulence modeling – Starting equations
Model Short description
Suitable for external aerodynamics, tubomachinery and high speed flows. Good for mildly
complex external/internal flows and boundary layer flows under pressure gradient (e.g. airfoils,
Spalart-Allmaras wings, airplane fuselages, ship hulls). Performs poorly for free shear flows and flows with strong
NSE
separation.
Robust. Widely used despite the known limitations of the model. Performs poorly for complex
Standard k–epsilon flows involving severe pressure gradient, separation, strong streamline curvature. Suitable for
initial iterations, initial screening of alternative designs, and parametric studies.
Suitable for complex shear flows involving rapid strain, moderate swirl, vortices, and locally
transitional flows (e.g. boundary layer separation, massive separation, and vortex shedding
Realizable k–epsilon behind bluff bodies, stall in wide-angle diffusers, room ventilation). It overcome the limitations of Additional closure equations for the turbulence models
the standard k-epsilon model.
Superior performance for wall-bounded boundary layer, free shear, and low Reynolds number
Standard k–omega flows compared to models from the k-epsilon family. Suitable for complex boundary layer flows • Equations cannot be derived from fundamental principles.
under adverse pressure gradient and separation (external aerodynamics and turbomachinery).
• All turbulence models contain some sort of empiricism.
Offers similar benefits as standard k–omega. Not overly sensitive to inlet boundary conditions • Some calibration to observed physical solutions is contained in the turbulence
SST k–omega like the standard k–omega. Provides more accurate prediction of flow separation than other models.
RANS models. Probably the most widely used RANS model.
• Also, some intelligent guessing is used.
1104 • A lot of uncertainty is involved! 1105
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
• The Reynolds stress tensor can be modeled using the Boussinesq hypothesis,
Reynolds stress models, non-linear eddy viscosity models or algebraic models.
If we retain this term we talk about URANS equations and if we drop it we talk about RANS equations
• The Reynolds stress model (RSM), probably is the most physically sound RANS
model as it derives its own governing equations (six new equations as the tensor is
symmetric).
• To derive the RANS equations we used Reynolds decomposition (and a lot of algebra
is involved), • However, it is much simpler to model the Reynolds stress tensor by means of the
Boussinesq hypothesis, which will be briefly outlined next.
• It is important to know the capabilities and limitations of each model.
1106 1107
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
• In the previous equation, denotes the strain-rate tensor. • LES/DES models are intrinsically unsteady and three-dimensional.
• is the identity matrix. • Let us take a look at the governing equations of the RANS model.
• is the turbulent eddy viscosity. • Remember, the main goal of the RANS turbulence models is to Reynolds stress
tensor and the turbulent eddy viscosity.
• is the turbulent eddy viscosity.
• At the end of the day we want to determine the turbulent eddy viscosity.
• The turbulent eddy viscosity is not a fluid property, it is a property needed by the
turbulence model.
• And each model will compute this quantity in a different way. 1108 1109
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
1110 • By the way, use these guidelines for external aerodynamics only. 1111
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 primitive patch (the patch
• Follow these guidelines to find the boundary conditions for the near-wall treatment. type 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 nutUSpaldingWallFunction** or
nut(–)WallFunction* 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
1112 ** For scalable wall functions 1113
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
A crash introduction to turbulence modeling in OpenFOAM® A crash introduction to turbulence modeling in OpenFOAM®
1116 1117
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-
wise ( ) directions.
4.
• DES and RANS simulations do not have stream-wise and span-wise wall distance units
requirements as in LES simulations. Therefore, they are more affordable.
You desired value
5. • Typical requirements for LES are:
1118 1119
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. • Set reasonable boundary and initial conditions for the turbulence model variables.
• Try to avoid the use of turbulent models with laminar flows. • Always monitor the turbulent variables, some of them are positive bounded.
• Choose the near-wall treatment and estimate before generating the mesh. • Avoid strong oscillations of the turbulent variables.
• Run the simulation for a few time steps and get a better prediction of and • If you are doing LES, remember that these models are intrinsically 3D and unsteady.
correct your initial prediction of . You should choose your time-step in such a way to get a CFL of less than 1 and
• The realizable or models are good choices for general preferably of about 0.5.
applications. • If you are doing RANS, it is perfectly fine to use upwind to discretize the turbulence
• The standard model is very reliable, you can use it to get initial values. closure equations. After all, turbulence is a dissipative process. However, some
authors may disagree with this, make your own conclusions.
• If you are interested in resolving the large eddies and modeling the smallest eddies,
DES or LES are the right choice. • If you are doing unsteady simulations, always remember to compute the average
values (ensemble average).
• If you do not have any restriction in the near wall treatment method, use wall
functions (even with LES/DES models). • If you are dealing with external aerodynamics and detached flows, DES simulations
are really affordable.
• Be aware of the limitations of the turbulence model chosen, find and read the original
references used to implement the model in OpenFOAM®. • The work-horse of turbulence modeling in CFD: RANS
1120 1121
A crash introduction to turbulence modeling in OpenFOAM® Turbulence hands-on tutorials
References
• Turbulent Flows
Stephen B. Pope • Vortex shedding past square cylinder
• Turbulence Modeling for CFD
David C. Wilcox • Let us run this case. Go to the directory:
• Turbulence: An Introduction for Scientists and Engineers
P. A. Davidson
• Large Eddy Simulation for Incompressible Flows $PTOFC/advanced_physics/turbulence/squarecil
Pierre Sagaut
• A First Course in Turbulence
H. Tennekes and J. L. Lumley
• Boundary-Layer Theory
• From this point on, please follow me.
H. Schlichting
• https://turbmodels.larc.nasa.gov/ • We are all going to work at the same pace.
• Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
1122 1123
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.
1124 1125
Turbulence hands-on tutorials Turbulence hands-on tutorials
Vortex shedding past square cylinder Vortex shedding past square cylinder
• We select the turbulence model in the turbulenceProperties dictionary file.
• We will use this case to learn how to setup a turbulent case (RANS and
LES). • This dictionary file is located in the directory constant.
• To select the K-Omega SST turbulence model,
• To run this case we will use the solvers simpleFoam (steady solver) and
pimpleFoam (unsteady solver).
17 simulationType RAS; RANS type simulation
• To get fast outcomes, we will use a coarse mesh. But feel free to refine the 18
mesh, specially close to the walls. 19
20
RAS
{
RANS sub-dictionary
1126 1127
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).
1128 1129
Turbulence hands-on tutorials Turbulence hands-on tutorials
Vortex shedding past square cylinder Vortex shedding past square cylinder
• The initial value for the turbulent kinetic energy can be found as follows, • At this point, we are ready to run the simulation.
• To run the tutorial using simpleFoam (RANS simulation), type in the terminal:
1. $> foamCleanTutorials
2. $> blockMesh
• The initial value for the specific kinetic energy can be found as follows,
3. $> checkMesh
4. $> rm -r 0
5. $> cp -r 0_org 0
• Use the following initial estimates, and 6. $> decomposePar
7. $> mpirun -np 4 renumberMesh -overwrite -parallel
• At this point, we are ready to run. But before running, remember to setup the right 8. $> mpirun -np 4 simpleFoam -parallel | tee log
numerics in the dictionary files fvSolution and fvSchemes.
9. $> mpirun -np 4 simpleFoam –postProcess –func Q -parallel
• Also, for the LES simulation try to keep the CFL number below 0.9
10. $> mpirun -np 4 simpleFoam –postProcess –func yPlus -parallel
• Finally, do not forget to setup the functionObjects to compute the forces, do the $> reconstructPar
11.
sampling, and compute y+ on-the-fly.
1130 12. $> paraFoam 1131
1132 1133
Turbulence hands-on tutorials Turbulence hands-on tutorials
Vortex shedding past square cylinder Vortex shedding past square cylinder
• To run the tutorial using pimpleFoam (LES simulation), type in the terminal: • In step 1, we clean the case directory. This is not compulsory, but it is highly advisable.
• In steps 2 and 3 we generate the mesh and check its quality.
10. $> decomposePar
• In steps 4-5, we transfer the backup or original files to the directory 0. It is highly advisable to
11. $> mpirun -np 4 renumberMesh -overwrite -parallel always keep backup files.
$> mpirun -np 4 pimpleFoam -parallel > log | tail -f log • In steps 6-8, we use the utility refineWallLayer to refine the mesh close to the walls (square
12.
in this case). This is helpful if you do not want to regenerate the mesh.
13. $> mpirun -np 4 pimpleFoam –postProcess –func Q -parallel
• In step 9, we interpolate the solution obtained using a RANS method on a coarse mesh, into the
14. $> mpirun -np 4 pimpleFoam –postProcess –func yPlus -parallel current finer mesh (the mesh was refined in steps 6-8).
15. $> reconstructPar • In step 10 we decompose the mesh. At this point we are preparing to run in parallel.
• In step 11 we use renumberMesh to reduce the bandwidth of the coefficient matrices.
16. $> paraFoam
• In step 12 we run in parallel and save the standard output in the file log.
• In step 13 we compute the Q-criterion using the utility postProcess.
• In step 14 we compute the yPlus using the utility postProcess.
• In step 15 we reconstruct the solution.
• In step 16 we use paraFoam to visualize the solution.
1134 1135
$PTOFC/advanced_physics/turbulence/flatPlate
• It does not matter your geometry or flow conditions, if you are resolving well the • We will also show you how to do the post-processing in order to reproduce the law of
turbulent flow, you should be able to recover this profile. the wall. For this, we will use a jupyter notebook (a python script).
• To compute this plot, you must sample the wall shear stresses. • Remember, as we are introducing new closure equations for the turbulence problem,
we need to define initial and boundary conditions for the new variables.
• Then, you can compute the shear velocity, friction coefficient, and u+ and y+ values.
• We also need to define the discretization schemes and linear solvers to use to solve
the new variables.
• It is also a good idea to setup a few functionObjects, such as: y+, minimum and
maximum values, forces, time average, and online sampling.
• You will find the instructions of how to run this case in the file README.FIRST
located in the case directory.
1138 1139
1140 1141
A crash Introduction to multiphase flows modeling OpenFOAM® A crash Introduction to multiphase flows modeling OpenFOAM®
Multiphase flows in industry and nature Multiphase flows in industry and nature
• Multiphase flows are very common in industry and in nature, the following • Multiphase flows are very common in industry and in nature, the following
are a few examples depending on the state of the different phase. are a few examples depending on the state of the different phase.
A crash Introduction to multiphase flows modeling OpenFOAM® A crash Introduction to multiphase flows modeling OpenFOAM®
Municipal and industrial water treatment Cargo ship wake Cooling Towers Volcano eruption
https://whatiswatertreatment.wordpress.com/what-are-the-systems-associated-with-water-
http://www.asiapacific.basf.com/apex/AP/en/upload/Press2010/BASF-Water-Chem-2010-Paper- http://developeconomies.com/development-economics/how-to-get-america-back-on-track-free-trade-edition/ http://americanpreppersnetwork.com/2014/08/preparing-volcano-eruption.html
treatment-and-how-are-they-treated/103-2/
Chem-2010-Intex-Shanghai
1144 1145
A crash Introduction to multiphase flows modeling OpenFOAM® A crash Introduction to multiphase flows modeling OpenFOAM®
Classifying multiphase flows according to phase morphology Why simulating multiphase flows is challenging?
• Simulating multiphase flows is not an easy task.
• Disperse system: the phase is dispersed as non-contiguous isolated
regions within the other phase (the continuous phase) . When we work with a • The complex nature of multiphase flows is due to:
disperse phase we say that the system is dispersed: disperse-continuous • More than one working fluid.
flow. • The transient nature of the flows.
• Separated system: the phase is contiguous throughout the domain and • The existence of dynamically changing interfaces.
there is one well defined interphase with the other phase. When we work • Significant discontinuities (fluid properties and fluid separation).
with continuous phases we say that the system is separated: continuous-
• Complicated flow field near the interface.
continuous flow.
• Interaction of small scale structures (bubbles and particles).
• Different spatial-temporal scales.
• Dispersed phases and particle-particle interactions.
• Mass transfer and phase change.
• Turbulence.
• Many models involved (drag, lift, heat transfer, turbulence dispersion,
Dispersed system Separated system
frictional stresses, collisions, kinetic theory, and so on).
1146 1147
A crash Introduction to multiphase flows modeling OpenFOAM® A crash Introduction to multiphase flows modeling OpenFOAM®
Modeling requirements
• It is necessary to account for the cascade
are resolved.
Computational power
effect of the various flow physics at
different scales: Large bubbles
(system scale) • Eulerian-Lagrangian: solves idealized
• Large flow structures within the fluid Medium bubbles isolated particles that are transported
flow (system-scale). (system-scales)
with the flow. One- or two-way coupling
• Local structural changes due to is possible. Can account for turbulence,
coalescence and breakage processes momentum transfer, and mass transfer.
(meso-scales). Small bubbles interaction
(meso-scales) • Eulerian-eulerian: solves two or more
• Motion and interaction of discrete
constituents or small particles (micro-
co-existing fluids. The system can be
scale). dispersed or separated, and can account
Bubble break-up
And coalescence
for turbulence, momentum transfer, and Increase
(meso-scales) Small sized particles
(micro-scales)
mass transfer.
MPF-1148 1148 1149
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 How to treat the wide range of behaviors in
multiphase flows Free surface multiphase flows Bubbles larger than cell size
Cell size
Eulerian-Eulerian approach
Eulerian-Eulerian approach Eulerian-Lagragian approach
(Multi-fluid and mixture
(VOF) (Particle tracking)
models)
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 How to treat the wide range of behaviors in
multiphase flows
Not ok. Only one cell to resolve the bubble. multiphase flows
VOF ≈ 0.5
Average phase
properties
How to treat the wide range of behaviors in How to treat the wide range of behaviors in
multiphase flows multiphase flows
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 Numerical approaches for multiphase flows
multiphase flows
Eulerian-Eulerian Eulerian-Eulerian
Eulerian-Lagrangian
(VOF) (Dispersed systems)
The particles position is
tracked by solving an ODE
for each particle
The continuous phase is • Non-interpenetrating • Interpenetrating continua. • Continuous phase:
solve in the mesh continua. Eulerian.
• Continuous phase:
• Continuous phases: Eulerian. • Dispersed phase:
Eulerian. Lagrangian.
• Dispersed phase: Eulerian.
• Fluid properties are written • Phase-weighted averages. • Solves ODEs for particle
on either side of the tracking (for every single
interface (no averaging). • Solves PDEs for all phases particle).
• In the Eulerian-Lagrangian framework, the continuous phase is solved in an Eulerian reference (including interphase
system and the particles or dispersed phase is solved in a Lagrangian reference system. • Solves one single set of transfer terms): mass, • Solves a set of PDEs for
PDEs: mass, momentum, momentum, energy. the continuous phase:
• The particles can be smaller or larger than the grid size.
energy. mass, momentum, energy.
• The particles can be transported passively or they can be coupled with the fluid governing • It can deal with gas-liquid,
equations. • Phase interaction terms
gas-solid, and liquid-solid
(including interphase
• It accounts for particle interaction and mass transfer. interactions.
transfer terms).
• The particles can interact with the boundaries and have a fate. 1156 1157
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. 1158 1159
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
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
A crash Introduction to multiphase flows modeling OpenFOAM® A crash Introduction to multiphase flows modeling OpenFOAM®
Volume-of-Fluid (VOF) governing equations for separated systems Eulerian-Eulerian governing equations for dispersed systems
• The Eulerian-Eulerian approach solves the governing equations for each phase, it
• For example, in the case of two phases treats the phases as interpenetrating continua.
where phase 1 is represented by and
0 0 0 0.1 0.3 • The incompressible, isothermal governing equations with interface tracking can be
phase 2 is represented by ; a volume
written as follows,
fraction value of 1 indicates that the cell is fill 0 0 0.3 0.8 1 Surface tension - Continuum surface force (CSF)
with phase 1; a volume fraction of 0.8
indicates that the cell contains 80% of a 0 0.1 0.8 1 1 Interface forces or momentum transfer.
Bubbles interaction models
phase 1; and a volume fraction of 0, indicates
that the cell is fill with phase 2. 0 0.4 1 1 1
• The values between 0 and 1 can be seen as
Interface
the interface between the phases.
• The fluid properties can be written on either side of the interface as follows,
Source terms:
• Porous media
• Coriolis forces
• Centrifugal forces
• Mass transfer
• and so on …
1164 1165
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.
1170 1171
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;
1172 1173
A crash Introduction to multiphase flows modeling OpenFOAM® Multiphase flows hands-on tutorials
Some useful bibliographical references
• Computational Techniques for Multiphase Flows
•
G. H. Yeoh, J. Tu. 2009, Butterworth-Heinemann
Multiphase Flow Analysis Using Population Balance Modeling: Bubbles, Drops and Particles
• Free surface – Ship resistance simulation
•
G. H. Yeoh, C. P Cheung, J. Tu. 2013, Butterworth-Heinemann
Turbulence Modeling for CFD
• Let us run this case. Go to the directory:
D. Wilcox. 2006, DCW Industries.
• Error analysis and estimation in the Finite Volume method with applications to fluid flows.
H. Jasak. PhD Thesis. 1996. Imperial College, London.
$PTOFC/advanced_physics/multiphase/wigleyHull
• 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.
• Derivation, Implementation, and Validation of Computer Simulation Models for Gas-Solid Fluidized
Bed • From this point on, please follow me.
B. van Wachem. PhD Thesis. 2000, TUDelft.
• Gas-Particle flow in a vertical pipe with particle-particle intractions • We are all going to work at the same pace.
J. L. Sinclair, R. Jackson AIChE Journal. Volume 35, Issue 9, 1473-1486, September 1989
• Remember, $PTOFC is pointing to the path where you
unpacked the tutorials.
1174 1175
• 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.
}
• Feel free to reuse this setup.
Surface tension between phase1 sigma sigma [ 1 0 -2 0 0 0 0 ] 0.07;
and phase2
1178 1179
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 1180 Typical setup of boundary conditions for numerical towing tank simulations 1181
Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation Free surface – Ship resistance simulation
• OpenFOAM® solves the following modified volume fraction convective • MULES options in the fvSolution dictionary.
equation to track the interface between the phases, • The semi-implicit MULES offers significant speed-up and stability over the
explicit MULES.
“alpha.*”
{
MULESCorr yes; Turn on/off semi-implicit MULES
nAlphaSubCycles 1; For semi-implicit MULES use 1. Use 2 or more for
explicit MULES.
• 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. 1182
} 1183
• Additional notes on the fvSolution dictionary. • Finally, we need to set the discretization schemes
• This is done in the dictionary fvSchemes.
• In this dictionary we set the discretization method for every term appearing in the
Set to yes for high Reynolds flows, where
momentumPredictor yes; convection dominates governing equations.
Recommended value is 1 (equivalent to PISO). • Convective terms discretization is set as follows:
nOuterCorrectors 1; Increase to improve the stability of second
order time discretization schemes (LES
simulations).
divSchemes
These terms are related to the
• 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
1184
div(phi,alpha). 1185
Multiphase flows hands-on tutorials Multiphase flows hands-on tutorials
Free surface – Ship resistance simulation Free surface – Ship resistance simulation
• For time discretization we can use an unsteady formulation (Euler in this case). • A way to accelerate the convergence to steady state, is by using local time stepping.
• This scheme requires setting the time-step, and it should be choosing in such a way • In LTS or local time steeping, the time-step is manipulated for each individual cell in
that it resolves the mean physics. the mesh, making it as high as possible to enable the simulation to reach steady-
• Remember, as the free surface is a strong discontinuity, for stability and good state quickly.
resolution we need to use a CFL less than one for the interface courant. • When we use LTS, the transient solution is no longer time accurate.
• The stability and accuracy of the method are driven by the local CFL number of each
cell.
ddtSchemes
• To avoid instabilities caused by sudden changes in the time-step of each cell, the
{
local time-step can be smoothed and damped across the domain.
default Euler;
} • To enable LTS, we use the localEuler method.
ddtSchemes
• Hereafter, we are using what is know as global time stepping, that is, the CFL {
number is limited by the smallest cell. default localEuler;
• The simulation is time-accurate, but it requires a lot of CPU time to reach a steady }
state (if it reaches one).
1186 1187
• 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;
1188 1189
Roadmap A crash Introduction to compressible flows modeling OpenFOAM®
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® • In compressible flows, the thermodynamical variables are related via an
6. Scalar transport pluggable solver equation of state (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.
1190 1191
A crash Introduction to compressible flows modeling OpenFOAM® A crash Introduction to compressible flows modeling OpenFOAM®
NSE
A crash Introduction to compressible flows modeling OpenFOAM® A crash Introduction to compressible flows modeling OpenFOAM®
Thermal boundary layer vs. Viscous boundary layer Thermal boundary layer in function of Prandtl number (Pr)
Forced convection
• If you are dealing with turbulence, you will need to define the • The solvers are very sensitive to overshoots and undershoots in the
boundary conditions and initial conditions for the turbulent thermal gradients, so you need to use very aggressive limiters.
diffusivity. • If you are dealing with chemicals reactions or combustion, you need to
• Define discretization schemes and linear solvers for the new use accurate and stable methods (preferably TVD).
variables and equations. • TVD methods requires good meshes and CFL number below 1 for good
accuracy and stability.
• Remember to choose the near-wall treatment. • Using steady solvers requires tuning of the under-relaxation factors.
Usually, the default values do not work well.
• We have found that it is tricky to achieve convergence using a low-RE
approach with compressible flows (high speed). • The use local time stepping to reach steady state can improve the
1198
convergence rate. 1199
A crash Introduction to compressible flows modeling OpenFOAM® A crash Introduction to compressible flows modeling OpenFOAM®
• You will find the source code of all the compressible solvers in the directories: • High speed aerodynamics:
• OpenFOAM-5.x/applications/solvers/compressible • sonicFoam, rhoSimpleFoam, rhoPimpleFoam
• OpenFOAM-5.x/applications/solvers/combustion
• OpenFOAM-5.x/applications/solvers/heatTransfer • Buoyancy driven flows (including Boussinesq approximation):
• OpenFOAM-5.x/applications/solvers/lagrangian • buoyantBoussinesqPimpleFoam buoyantBoussinesqSimpleFoam,
buoyantSimpleFoam, buoyantPimpleFoam
• OpenFOAM-5.x/applications/solvers/multiphases
• You will find the source code of the thermophysical models in the directory: • Conjugate heat transfer
• OpenFOAM-5.x/src/thermophysicalModels • chtMultiRegionFoam
1200 1201
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®
• Remember, temperature is a bounded quantity so you need to use non-oscillatory methods. • Remember, temperature is a bounded quantity so you need to use non-oscillatory methods.
• For low speed flows, the kinetic energy K and the enthalpy h can be discretized using the linear • For low speed flows, the kinetic energy K and the internal energy e can be discretized using the
method. For high speed flows, is better to use bounded methods. linear method. For high speed flows, is better to use bounded methods.
• Remember to use gradient limiters. • Remember to use gradient limiters.
• If you are using a steady solver, remember to set the under relaxation factors for h, T, and rho.
1206 • If you are using a steady solver, remember to set the under relaxation factors for e, T, and rho.
1207
A crash Introduction to compressible flows modeling OpenFOAM® A crash Introduction to compressible flows modeling OpenFOAM®
$PTOFC/advanced_physics/compressible/2Dcylinder_plumes/buoyantPimpleFoam/
1212 1213
Compressible flows hands-on tutorials Compressible flows hands-on tutorials
2D supersonic cylinder – Shock waves
$PTOFC/advanced_physics/compressible/supersonic_cyl
• From this point on, please follow me. Shock wave visualization using numerical Schlieren (density gradient)
• We are all going to work at the same pace.
• Remember, $PTOFC is pointing to the path where you • The shock wake is a strong discontinuity that need to be treated using high resolution
unpacked the tutorials. schemes.
1214
• Additionally, the non-orthogonality add extra complications to this problem. 1215
• You will find the instructions of how to run the cases in the file README.FIRST
located in the case directory.
1216 1217
Roadmap A crash Introduction to moving bodies OpenFOAM®
1218 1219
A crash Introduction to moving bodies OpenFOAM® A crash Introduction to moving bodies OpenFOAM®
Moving bodies in OpenFOAM® – A few examples Moving bodies in OpenFOAM® – A few examples
http://www.wolfdynamics.com/training/movingbodies/image3.gif http://www.wolfdynamics.com/training/movingbodies/image4.gif
http://www.wolfdynamics.com/training/mphase/image32.gif http://www.wolfdynamics.com/training/mphase/image33.gif
1222 1223
• You will find the source code of the prescribed patch motion in the directory:
• OpenFOAM-5.x/src/fvMotionSolver/pointPatchFields/derived • From this point on, please follow me.
• We are all going to work at the same pace.
• You will find the source code of the restraints/constraints of rigid body motion solvers • Remember, $PTOFC is pointing to the path where you
in the directory: unpacked the tutorials.
• OpenFOAM-5.x/src/sixDoFRigidBodyMotion/sixDoFRigidBodyMotion
1224 1225
Moving bodies hands-on tutorials Moving bodies hands-on tutorials
Continuous stirring tank reactor – Sliding meshes and MRF Continuous stirring tank reactor – Sliding meshes and MRF
• We already created this mesh during the meshing module.
• We will only address the differences in meshing for a MRF simulation and a sliding mesh
simulation.
• In this case, at the end of the meshing stage we obtained a faceZone and a cellZone.
• This is a conforming mesh, that is, the cells in the interface of the inner and outer regions are
perfectly matching.
• For MRF simulations, the cellZone can be used to assign the MRF properties to the rotating
zone.
• For sliding meshes or non-conforming meshes, there is an extra step where we need to split the
mesh in two regions and create the interface patches between the fix zone and the rotating
zone (the solution will be interpolated in these patches).
Cell region 2
Sliding grids – Unsteady solver MRF – Steady solver (fix region)s
http://www.wolfdynamics.com/training/movingbodies/image6.gif http://www.wolfdynamics.com/training/movingbodies/image7.gif
1226 1227
Shaft Shaft
type rotatingWallVelocity; type rotatingWallVelocity;
origin (0 0 0); origin (0 0 0);
axis (0 0 1); axis (0 0 1);
omega constant 12.566370; omega constant 12.566370;
value uniform (0 0 0); value uniform (0 0 0);
Impeller Impeller
type movingWallVelocity; type movingWallVelocity;
value uniform (0 0 0); Inner region generated during value uniform (0 0 0); Inner region – dynamicMeshDict
meshing - MRFProperties
Arbitrary mesh interface –
createBafflesDicts
1228 1229
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
Shaft • For siding meshes, we need to create separated regions.
type rotatingWallVelocity;
origin (0 0 0); • In this case, to create the two regions we proceed as follows,
axis (0 0 1);
omega constant 12.566370;
value uniform (0 0 0);
• In step 1, we split the mesh in regions using the baffles (faceZone), created during the meshing
constant/dynamicMeshDict – For sliding meshes constant/MRFProperties – For MRF approach stage.
cellZone cell_inner_volume; • We also create the cyclicAMI patches AMI1 and AMI2.
dynamicFvMesh dynamicMotionSolverFvMesh; active yes;
motionSolverLibs ( "libfvMotionSolvers.so" ); • At this point we have two regions and one zone. However, the two regions are stich together
solver solidBody; // Fixed patches (by default they move’ with the MRF zone) via the patches AMI1 and AMI2.
cellZone cell_inner_volume; nonRotatingPatches ();
solidBodyMotionFunction rotatingMotion; • In step 2, we topologically split the patches AMI1 and AMI2. As we removed the link between
origin (0 0 0); origin (0 0 0); AMI1 and AMI2, the regions are free to move.
axis (0 0 1); axis (0 0 1);
omega constant 12.566370; omega constant 12.566370;
1230 1231
• The utility createBaffles, reads the dictionary createBafflesDict. • In sliding mesh simulations, the solution is interpolated back-and-forth
• With this utility we create the interface patches between the fix zone and the between the regions.
rotating zone. • The interpolation is done at the arbitrary mesh interface patches (AMI) .
• To reduce interpolation errors at the AMI patches, the meshes should be
baffles
similar in the master and slave patches.
{
rotating Name of the baffle group
{ AMI interface Fix domain
type faceZone; Use faceZone
zoneName face_inner_volume; Face to use to construct the AMI patches. http://www.wolfdynamics.com/training/movingbodies/image8.gif
The name was defined in snappyHexMeshDict
patches
{
master Parameters for the master patch
{
name AMI1; Name of the master patch (user defined)
Boundary condition type cyclicAMI;
for sliding grids matchTolerance 0.0001;
neighbourPatch AMI2; Neighbour patch (slave patch or AMI2)
transform noOrdering;
}
slave Parameters for the slave patch
{
Boundary condition name AMI2; Name of the slave patch (user defined)
type cyclicAMI;
for sliding grids matchTolerance 0.0001;
neighbourPatch AMI1; Neighbour patch (master patch or AMI1)
transform noOrdering;
}
}
}
} Initially, the master and slave patches Rotating domain Rotating patch Fix patch
share a common face 1232 Master patch Slave patch 1233
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
• At this point the mesh is ready to use. You can visualize the mesh using • The command moveDynamicMesh –checkAMI
paraFoam. will print on screen the quality of the AMI interfaces
for every time step.
• If you use checkMesh, it will report that there are two regions. • Ideally, you should get the AMI patches weights as
close as possible to one.
• In the dictionary constant/dynamicsMeshDict we set which region will
• Weight values close to one will guarantee a good
move and the rotation parameters. interpolation between the AMI patches.
• To preview the region motion, in the terminal type: http://www.wolfdynamics.com/training/movingbodies/image9.gif
• $> moveDynamicMesh … Name of the AMI patch Name of the AMI patch
…
…
• To preview the region motion and check the quality of the AMI interfaces, in Calculating AMI weights between owner patch: AMI1 and neighbour patch: AMI2
Number of faces in
the terminal type: AMI: Creating addressing and weights between 2476 source faces and 2476 target faces the AMI patches
• $> moveDynamicMesh -checkAMI -noFunctionObjects 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
…
• In our YouTube channel you can find an step-by-step video explaining …
this case. …
1234 1235
Method coefficients
21 solver displacementLaplacian; Solver for mesh motion
22 method
23 displacementLaplacianCoeffs
Cylinder prescribed motion – Oscillating motion 24 {
25 diffusivity inverseDistance (cylinder);
26 }
http://www.wolfdynamics.com/training/movingbodies/image11.gif
17 dynamicFvMesh dynamicMotionSolverFvMesh; Mesh motion library for
boundary patches
18
19 motionSolverLibs ("libsixDoFRigidBodyMotion.so"); Motion library
20
Method coefficients
23 sixDoFRigidBodyMotionCoeffs 50 constraints
24 { 51 {
25 patches (floatingObject); Moving patch 55 fixedAxis
26 56 {
Mesh deformation limits.
27 innerDistance 0.1; 57 sixDoFRigidBodyMotionConstraint axis;
The mesh will not be deformed in the fringe located within
28 outerDistance 0.4; 58 axis (0 1 0);
innerDistance and outerDistance (distance normal to the wall)
59 } Motion constraints
33 centreOfMass (0.5 0.5 0.5); If you do not give any
34 mass 5; Physical properties of the body 63 fixedLine constraint, the body is free
35 momentOfInertia (0.08 0.08 0.1); 64 { to move in all directions.
65 sixDoFRigidBodyMotionConstraint line;
37 report on; Report on screen position of the body 66 centreOfRotation (0.5 0.5 0.5);
38 67 direction (0 0 1);
outerDistance
68 }
45 solver
46 { 70 }
47 type Newmark; Rigid body motion solver Body restraints
48 } 72 restraints
Restraints can be used to
… 73 {
Body patch damp the acceleration of the
… body.
76 }
… In this case, we are not
using restraints
78 }
innerDistance
Set it to zero if you do not want to apply mesh morphing to the inner region 1246 1247
33 floatingObject
34 {
35 type movingWallVelocity;
36 value uniform (0 0 0);
37 }
1248 1249
Roadmap A crash Introduction to source terms OpenFOAM®
1250 1251
A crash Introduction to source terms OpenFOAM® A crash Introduction to source terms OpenFOAM®
• Filter source term • Using this source term we can apply a porous region (of the type Darcy-Forchheimer)
in the cell selection.
• Let us run this case. Go to the directory: • The source term is activated after 2 seconds of simulation time.
$PTOFC/advanced_physics/source_terms/filter/porous_source
Set of cell
(filter)
1260 1261
Scalar transport pluggable solver Scalar transport pluggable solver
Scalar transport pluggable solver Scalar transport pluggable solver hands-on tutorials
gradSchemes s1 $PTOFC/advanced_physics/source_terms/2Delbow_passive_scalar
{ {
default Gauss linear; solver smoothSolver;
grad(s1) cellLimited Gauss linear 1; smoother symGaussSeidel;
} tolerance 1e-08;
relTol 0;
}
divSchemes • From this point on, please follow me.
{
default none; • We are all going to work at the same pace.
div(phi,U) Gauss linearUpwindV default;
div(phi,s1) Gauss vanLeer; • Remember, $PTOFC is pointing to the path where you
} unpacked the tutorials.
1264 1265
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.
• At this point, we are ready to run the simulation.
• We will use the solver icoFoam.
• Remember to adjust the numerics according to your physics.
• Do not forget to create the boundary conditions and initial conditions of the
S1
U → (2 0 0) new field variables.
• You will find the instructions of how to run the cases in the file
README.FIRST located in the case directory.
http://www.wolfdynamics.com/training/sourceterms/image2.gif
S2
U → (0 3 0)
Enjoy OpenFOAM®
• OpenFOAM® – Turbulence Modeling
• OpenFOAM® – Computational heat transfer amd compressible flows
• OpenFOAM® – Advanced meshing
• OpenFOAM® – Basic programming
• Introduction to the Finite Volume Method
• DAKOTA – Optimization methods and code coupling
• Python – Programming, data visualization and exploratory data analysis
• Python and R – Data science and big data
• ParaView – Advanced scientific visualization and python scripting
• And many more available on request
• Besides consulting services, we also offer ‘Mentoring Days’ which are days of one-on-one
coaching and mentoring on your specific problem.
• For more information, ask your trainer, or visit our website
http://www.wolfdynamics.com/ 1270 1271