OpenFOAM Motorbike Tutorial
In Work - some information may be wrong! Also updating to OpenFOAM 2.1.1
The basis of the Vespa CFD modelling (to start with at least) is the OpenFOAM Motorbike tutorial. Here are some notes on that tutorial, the first thing that people will need to do is get the tutorial to run before adapting it for a Vespa. Nerd Warning: This is a techy process to set-up and to get working, involving Linux commands and compiling and stuff. Also maths is involved and these notes are from a non-CFD expert and therefore are an overly simplified perspective (which may help or hinder). Any CFD experts out there, please feel free to jump in and correct and contribute!
Getting Set Up
OpenFOAM is free but for Linux type OS's only. You can get OpenFOAM at http://www.openfoam.com/ http://www.caelinux.com
Running the Tutorial
There is general instruction on using OpenFOAM in their User Guide
<install_dir>/OpenFOAM-2.1.1/tutorials/incompressible/simpleFoam/motorBike
Below is the annotated (in brackets) OpenFOAM case file structure SST k-omega module
|-- 0.org ("time" directory starting with T=0, giving conditions from the initial step in time) | |-- U (flow velocity) | |-- include | | |-- fixedInlet | | |-- frontBackUpperPatches | | `-- initialConditions | |-- k (turbulence kenetic energy) | |-- nut (turbulence viscosity) | |-- omega (turbulence specific dissipation rate) | `-- p (pressure) |-- Allclean (precanned clean file) |-- Allrun (precanned run file) |-- constant (hard static stuff i.e. physical properties) | |-- RASProperties (Reynolds-Averaged Simulation Model to use e.g. kOmegaSST) | |-- polyMesh | | |-- blockMeshDict | | `-- boundary | |-- transportProperties (Transport Model e.g. Newtonian) | `-- triSurface | `-- motorBike.obj (this is the actual motorbike model that you can view with ParaView) `-- system (soft stuff i.e. the info on the computational system used to analyse the problem) |-- controlDict (the main dictionary for controlling the simulation) |-- decomposeParDict (dictionary for partitioning up the space into smaller chunks) |-- fvSchemes |-- fvSolution.org `-- snappyHexMeshDict (the dictionary for adding a mesh for simulating surface interactions)
The simpliest way to run the tutorial is to trust in blind faith and use "Allrun", this will give you are starting point knowing that everything actually works :) It also gives you a good idea of what is happening to get CFD happening with a motorbike (see output below)
cd $HOME/OpenFOAM/OpenFOAM-2.1.1 source etc/bashrc cd tutorials/incompressible/simpleFoam/motorBike/ ./Allrun Running blockMeshsnappyHexMeshpotentialFoamsimpleFoam
Also note the system/forceCoeffs dictionary for calculating Drag and Lift e.g. Aref the frontal area of the vehicle
http://cfdcomputing.com/drag_openfoam.htm
Looking at the Result
The above goes through and creates 5 time steps 0,100,200,400 and 500. Without going into detail of what all the data means, we can look at it and create pretty pictures with ParaView
You will also find some handy coefficient output in the log.simpleFOAM file (as of OpenFOAM 2.0.1). A coefficient is a number that allows you to compare a motorbike with a Vespa (both wasp and scooter) or a Boeing 747 by removing the size factor and giving a relative number that expresses the "nessness" of something. By "nessness" think of some descriptive property you want measure and have more or less of, e.g. smoothness. In the output below the "draginess" of this motorbike is the Cd (proper name Drag Coefficient) and it is a number that you'd like to be as close to zero as possible (a Boeing 747 will have a much lower number though but won't fly at all with a Vespa engine bolted on).
Drag Coefficient (Cd) http://en.wikipedia.org/wiki/Drag_coefficient
http://en.wikipedia.org/wiki/Lift_coefficient
http://en.wikipedia.org/wiki/Pitching_moment
forceCoeffs output: Cd = 0.416234 Cl = 0.0663582 Cm = 0.151496
Look at the numbers at the bottom of the file. The simulation takes a while to "converge", which means that all the simulated bits take a little time to balance out the math, so they start by having wildly varying values and the end results "should" (you need to check) have more consistent values.
More CPU (GPU?) Power
Depending on your system you are likely to be waiting around a while for the result. On an Intel Core i7 CPU @ 3.07GHz the result will take about 16 minutes. If you use the Linux "top" you will see it is only running on one process(core) rather than the full 8 cores. So we have a V8 but we are only running on one cylinder. Let's give it some more power...
Ref: http://www.openfoam.com/docs/user/running-applications-parallel.php
First do an ./Allclean of the motorbike directory and then make a copy (we want to keep the original as-is for reference). e.g. cp -r motorbike motorbikeParallel6
It appears that OpenFOAM started to play with adding a parallel bit in the tutorial because there is already a system/decomposeParDict there. This describes how we break up the problem into smaller bits so we can give a bit to each core. This is set to use 6 CPU. To make use if this, alter the Allrun as follows:
#!/bin/sh # Source tutorial run functions . $WM_PROJECT_DIR/bin/tools/RunFunctions cp -r 0.org 0 > /dev/null 2>&1 runApplication blockMesh runApplication snappyHexMesh -overwrite runApplication potentialFoam -noFunctionObjects -writep # runApplication `getApplication` runApplication decomposePar runParallel `getApplication` 6 runApplication reconstructPar
With the above we reduce the 16 minute execution time down to 10 minutes. We are using 6 cores out of 8 but won't bother using the other 2 cores at the moment because, until we configure the partitioning to suit, we won't get much more speed-up. We'll revisit this when we start asking it to solve bigger problems more accurately. To run the case on a 4 core processor e.g. Intel Core Quad
Once we have run the job in parallel we can do a check to see if the numbers are roughly the same:
forceCoeffs output: Cd = 0.415571 Cl = 0.0671005 Cm = 0.15037
GPU's
Below is some info that was added but I have not yet confirmed working with the motorBike tut
TODO: See if we can make this even faster with GPU's e.g. with details below
Symscape ofgpu http://www.symscape.com/gpu-0-2-openfoam
SpeedIT http://issuu.com/vratis/docs/arael_oct_2011?mode=window&backgroundColor=%23222222
CNC (Concurrent Number Cruncher) http://www.geocities.co.jp/SiliconValley-SantaClara/1183/study/OpenFOAM/CNC/CNC.html
These libraries transfer the calculation to your NVIDIA graphics card or a TESLA card. NVIDIA TESLA cards are expensive parallel processing cards offering significant double precision performance that can be leveraged using SpeedIT extreme. The other libraries offer "only" single precision support. Double precision support on NVIDIA graphics cards is very limited for NVIDIA TESLA marketing reasons. NVIDIA graphics cards offer very high single precision performance e.g. GTX 480 1344 GFlop/s (but only 168 GFlop/s double precision). Modern CPUs offer less than 100 GFlop/s double precision. I compared the double precision performance of an Intel 9550 with a GTX 480 using SpeedIT extreme. Running the case in parallel on the Intel 9550 was always faster. I assume this was caused by the PCI bottleneck (data transfer between memory and GPU via PCI is much slower than data transfer between CPU and memory via mainboard bus). Nevertheless running large cases in single precision (this is where GPUs perform best due to technical/PCI bottleneck reasons) using Symscape ofgpu and a NVIDIA graphics card should result in a performance boost in the range of 5x to 15x compared to an Intel Core Quad
Benchmark based on Symscape ofgpu and OpenFoam sample case pitzDaily:
System CPU: AMD Opteron 6134
commands: blockMesh and simpleFoam
For 12225 Cells:
Note: GPU processing is only effective with high numbers of cells!
More Speed
The precanned tutorial is like a virtual wind tunnel and we can see the speed that the motorbike is being tested at within the 0.org/include/initialConditions file. This is the "flowVelocity (20 0 0)" parameter which is 20m/s or 72km/hr. Lets create some different cases for some more exciting speeds of 100km/hr (28m/s), 130km/hr (36m/s) and 160km/hr (45m/s). This should give us some good comparison runs for a Vespa running at highway speeds in different countries and an extreme example in racing.
Lets create the 100km/hr case first
../Allclean (remove results from motorBike run) cd .. cp -rf motorbikeParallelx motorBike motorBike_100
And adjust the bits in motorBike_100/0.org/include/initialConditions
/*--------------------------------*- C++ -*----------------------------------*\ | ========= | | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | | \\ / O peration | Version: 2.0.1 | | \\ / A nd | Web: www.OpenFOAM.com\\/28
So the forces are calculated correctly you also need to change the magUInf
Then we can run is as before with the ./Allrun command from within the motorBike_100 directory.
We can do the same for 130km/hr (36m/s) and 160km/hr (45m/s).
We should see similar results for the force coefficients
forceCoeffs output: Cd = 0.41525 Cl = 0.0671618 Cm = 0.150203
More Accuracy
Increasing mesh resolution
Here we will talk about blockMeshdict
Increasing snappyHexMesh accuracy
Here we will talk about improving the accuracy around the model
Results of using various parameters for mesh size, resolution, etc
Validating the Model
A lot of blind faith was used in the above. Before we jump into the Vespa version, we'll test a few things to make sure that the data we are getting makes sense.
Checking for Errors
The first step in making sure everything is ok is checking the output logs from the OpenFOAM run, this will show if the run actually worked or not. For each stage there is a log.<stage> output. Below is some errors and fixes (please add as they are found)
log.simpleFoam error
When running with the original single CPU job I get:
simpleFoam: symbol lookup error: /home/pmcintos/OpenFOAM/OpenFOAM-2.0.1/platforms/linux64GccDPOpt/lib/libincompressibleLESModels.so: undefined symbol: _ZN4Foam8LESdelta34destroydictionaryConstructorTablesEv
This was fixed by upgrading to Centos 6.0. This is probably not an issue though as it is only at the end of the log file (not at each iteration) and the name "destroy" indicates it is just part of the memory clean up process (the process ends anyway).
OpenFOAM Checking Utilties
As we will be adding our own Vespa mesh and tinkering with it to test various things out, we'll need to check the model and make sure that OpenFOAM thinks it is ok. Let's check the motorcycle using surfaceCheck, we see below that there are some problems.
surfaceCheck motorBike.stl | grep illegal Surface has 60941 illegal triangles. Dumping conflicting face labels to "illegalFaces"
To fix the problems use "clean" while converting from stl to stl.
surfaceConvert -clean motorBike.stl motorBike_clean.stl | grep illegal Removing 67326 illegal faces. surfaceCheck motorBike_clean.stl | grep illegal Surface has no illegal triangles.
Now we can replace the dirty motorbike with the clean one and run the simulation again.
forceCoeffs output: Cd = 0.416234 Cl = 0.0663582 Cm = 0.151496
Checking the Result with Reality
Note: there is a question mark on if Cd means Cd or CdA...
From the above we see drag coefficent of Cd = 0.416. Unfortunately the motorcycle make and model is not known and it would be hard anyway to find what the actual Cd was in reality with owning one yourself. 0.416 is pretty low but the motorbike does look pretty sporty so it is possible that the values are correct. So it looks OK(?) but the only real way to check is to validate the results with some real world test. Since this is Vespa Labs, well leave the motorbike stuff here and start working on the OpenFOAM Vespa Tutorial