CFD Analysis of a Server Room

Simulate server room airflow and temperature using OpenFOAM and ParaView.

Introduction

30 Second Summary

Every server room generates heat. If the cooling system can't keep up, servers overheat and go offline. Building services engineers use CFD simulations to predict airflow and temperature patterns before a single vent is installed.

In this project, you will run a complete CFD ventilation analysis of a simplified server room using OpenFOAM. You will simulate airflow and temperature distribution, visualize the results in ParaView, and write a professional technical report ready to show employers.

What You'll Build

A fully configured OpenFOAM simulation of a server room with a cool air supply inlet, a warm air exhaust outlet, and a heated floor representing server rack heat output, plus ParaView visualizations and a consulting-grade CFD report.

By the end of this project, you'll have:

  • A converged OpenFOAM case with mesh, boundary conditions, and a steady-state solution produced by the buoyantBoussinesqSimpleFoam solver.
  • Professional-quality ParaView visualizations showing temperature contours, velocity vectors, streamlines, and a cross-section temperature profile.
  • A structured CFD technical report with methodology, results, and engineering recommendations, following the format used by building services consultancies.
  • Secret Mission: Run a parametric study comparing two supply air temperatures and add a design comparison section to your report.

Are there any prerequisites?

This project assumes a basic understanding of fluid dynamics and heat transfer. You will also need a Windows PC with WSL2 support (Windows 10 build 19041 or higher, or Windows 11).

If you have used commercial CFD tools like StarCCM+ or ANSYS Fluent before, you will find many of the concepts familiar. OpenFOAM uses text-based configuration files instead of a GUI, so the workflow feels different but the underlying physics is the same.

Before We Start

Before We Start...

Set Up OpenFOAM and ParaView on Windows

Before you can simulate airflow in a server room, you need a CFD solver and a visualization tool.

OpenFOAM is an open-source CFD toolkit that runs on Linux. On Windows, you will run it inside WSL2 (Windows Subsystem for Linux), which gives you a full Ubuntu environment without dual-booting. ParaView runs natively on Windows for the best graphics performance when visualizing your results.

In this step, get ready to:
  • Install WSL2 with Ubuntu 22.04 on your Windows PC.
  • Install OpenFOAM v2412 inside Ubuntu and verify it works.
  • Install ParaView 6.0.1 on Windows for post-processing your simulation results.
Install WSL2 and Ubuntu

WSL2 lets you run a full Linux kernel inside Windows. OpenFOAM requires Linux, so WSL2 is the bridge that makes this work without leaving your Windows environment.

  • Press the Windows key to open your search bar.
  • Type PowerShell and select Run as administrator.
  • Install WSL2 with Ubuntu 22.04 by running this command:
wsl --install -d Ubuntu-22.04

What does this command do?

This enables the WSL2 feature on your Windows PC and downloads the Ubuntu 22.04 Linux distribution. It handles all the virtualization setup automatically.

  • Restart your PC when prompted.
  • After rebooting, Ubuntu will open automatically (or open it from the Start menu) to complete initial setup.
  • Create a Linux username and password when prompted. This is separate from your Windows login.
  • Verify WSL2 is running correctly by opening a new PowerShell window and running:
wsl -l -v

You should see Ubuntu-22.04 listed with VERSION set to 2. This confirms WSL2 is active.

WSL install failed or you don't see version 2?

WSL2 requires Windows 10 build 19041 or higher, or Windows 11. Check your Windows version by pressing Windows + R, typing winver, and pressing Enter.

If your build number is below 19041, you need to update Windows before WSL2 will work.

Help me troubleshoot my WSL2 installation

Install OpenFOAM v2412

OpenFOAM v2412 is the CFD toolkit you will use to solve the buoyancy-driven airflow equations. You install it inside your Ubuntu environment using the official ESI package repository.

  • Open your Ubuntu terminal. You can find it by pressing the Windows key and typing Ubuntu.
  • Add the OpenFOAM package repository by running this command:
curl -s https://dl.openfoam.com/add-debian-repo.sh | sudo bash
  • Enter your Linux password when prompted. You will not see characters as you type. This is normal.
  • Update the package lists and install OpenFOAM by running these commands:
sudo apt-get update
sudo apt-get install openfoam2412-default
  • Type Y and press Enter when asked to confirm the installation.

What does this install?

The openfoam2412-default package includes all the solvers (like buoyantBoussinesqSimpleFoam), meshing utilities (like blockMesh), and post-processing tools you need for this project. The download is several hundred MB, so it may take a few minutes depending on your connection.

OpenFOAM needs its environment variables loaded every time you open a terminal. You will add this to your shell configuration so it happens automatically.

  • Add OpenFOAM to your shell environment by running these commands:
echo "source /usr/lib/openfoam/openfoam2412/etc/bashrc" >> ~/.bashrc
source ~/.bashrc

What does this do?

The first line appends the OpenFOAM environment setup script to your ~/.bashrc file, which runs automatically each time you open a terminal. The second line reloads ~/.bashrc so the changes take effect immediately in your current session.

  • Verify OpenFOAM is working by running:
blockMesh -help

You should see help text describing the blockMesh utility and its options. This confirms OpenFOAM is installed and accessible.

Command not found when running blockMesh?

This means the OpenFOAM environment is not loaded. Try running source ~/.bashrc again, then retry blockMesh -help.

If that does not fix it, check your ~/.bashrc file contains the line source /usr/lib/openfoam/openfoam2412/etc/bashrc at the bottom. You can view it by running cat ~/.bashrc.

Help me fix my OpenFOAM installation

Install ParaView on Windows

ParaView is the visualization tool you will use to create temperature contours, velocity vectors, and cross-section plots from your simulation results. You install it natively on Windows for the best graphics performance.

Why install ParaView on Windows instead of inside WSL?

ParaView inside WSL can crash due to graphics library conflicts with Qt. Running ParaView natively on Windows avoids this entirely and gives you full hardware-accelerated rendering.

  • Open your web browser and navigate to the ParaView downloads page.
  • Download the Windows MPI installer: ParaView-6.0.1-MPI-Windows-Python3.12-msvc2017-AMD64.msi (approximately 498 MB).
  • Run the MSI installer and follow the prompts to complete installation.
  • Press the Windows key to open your search bar.
  • Type ParaView and press Enter to open it.

You should see the ParaView application window open with a pipeline browser on the left and a 3D viewport in the centre. This confirms the installation was successful.

ParaView won't open or shows an error?

Make sure you downloaded the MSI installer (not the .zip archive). If you see a Windows Defender warning, click More info then Run anyway to proceed.

Help me get ParaView working on Windows

Your environment is fully set up. Next up, you will build the server room geometry using OpenFOAM's blockMesh utility and define the 3D computational domain for your simulation.

Build the Server Room Geometry

Your tools are installed and ready. Now it's time to define the physical space you'll be simulating.

Every CFD simulation starts with geometry. You need to tell OpenFOAM the shape of the room, where air enters and exits, and which surfaces produce heat. In this step, you'll create the case directory structure and generate a 3D mesh of the server room using blockMesh.

In this step, get ready to:
  • Create the OpenFOAM case directory structure with gravity definition.
  • Define the server room geometry and mesh resolution in blockMeshDict.
  • Generate and verify the mesh quality.
Create the OpenFOAM case directory structure

OpenFOAM organizes every simulation as a "case" directory with three required subdirectories. The 0/ folder holds initial conditions, constant/ holds physical properties, and system/ holds solver settings.

  • Open your Ubuntu terminal (via Windows Terminal or the Start menu).
  • Navigate to your home directory and create the case folder with all subdirectories by running these commands:
cd ~
mkdir -p serverRoom/{0,constant,system}
cd serverRoom
  • Confirm the directories were created by running:
ls

You should see 0, constant, and system listed in the output.

Don't see the three folders?

Make sure you ran the commands from your home directory. Run cd ~ first, then try the mkdir -p command again.

help me create the OpenFOAM case directory structure

Now you need to define gravity for the simulation. The server room uses the y-axis as the vertical direction, so gravity points downward at -9.81 m/s².

  • Create the gravity file by opening a new file in nano:
nano constant/g
  • Paste the following content into the editor:
FoamFile
{
    version     2.0;
    format      ascii;
    class       uniformDimensionedVectorField;
    object      g;
}

// Gravitational acceleration in m/s^2
// Points in negative y direction (downward)
dimensions      [0 1 -2 0 0 0 0];
value           (0 -9.81 0);

What does this file do?

The FoamFile header is required in every OpenFOAM dictionary file. It tells OpenFOAM what type of data the file contains.

The dimensions line specifies the physical units using OpenFOAM's dimensional system (kg, m, s, K, mol, A, cd). The value [0 1 -2 0 0 0 0] means metres per second squared. The value (0 -9.81 0) applies gravity in the negative y direction.

  • Save and exit nano by pressing **Ctrl+O**, then **Enter** to confirm the filename, then **Ctrl+X** to exit.
  • Confirm the file was created by running:
ls constant/

You should see g listed in the output.

File not appearing?

Make sure you pressed **Ctrl+O** (the letter O, not zero) to save before exiting. If you pressed **Ctrl+X** without saving, nano may have discarded your changes.

Also confirm you're in the serverRoom directory by running pwd. It should show /home/<your-username>/serverRoom.

help me create the gravity file in OpenFOAM

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete constant/g file for comparison:

FoamFile
{
    version     2.0;
    format      ascii;
    class       uniformDimensionedVectorField;
    object      g;
}

dimensions      [0 1 -2 0 0 0 0];
value           (0 -9.81 0);
Define the room geometry in blockMeshDict

The blockMeshDict file is where you define the room's shape, size, and mesh resolution. You'll describe a 6m (length) x 3m (height) x 4m (width) rectangular server room as a single hexahedral block with 9,000 cells.

What is a hexahedral mesh?

A hexahedral mesh divides your room into small brick-shaped cells. Each cell is a six-sided box. For a rectangular room like this one, hexahedral cells are the most efficient and accurate choice.

The resolution of 30 x 15 x 20 cells means the room is split into 30 slices along its length, 15 along its height, and 20 along its width. That gives 9,000 cells total, enough to capture the airflow patterns without taking too long to solve.

  • Create the blockMeshDict file by running:
nano system/blockMeshDict
  • Paste the following content into the editor:
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}

// All dimensions in metres
scale   1;

// 8 vertices defining the corners of the room
// Room is 6m long (x), 3m tall (y), 4m wide (z)
vertices
(
    (0 0 0)
    (6 0 0)
    (6 3 0)
    (0 3 0)
    (0 0 4)
    (6 0 4)
    (6 3 4)
    (0 3 4)
);

// One hex block using all 8 vertices
// 30 x 15 x 20 cells = 9,000 total
blocks
(
    hex (0 1 2 3 4 5 6 7) (30 15 20) simpleGrading (1 1 1)
);

edges
(
);

// Define named boundary patches
boundary
(
    // Cool air supply from CRAC unit (x=0 wall)
    inlet
    {
        type patch;
        faces
        (
            (0 4 7 3)
        );
    }
    // Warm air exhaust (x=6 wall)
    outlet
    {
        type patch;
        faces
        (
            (1 2 6 5)
        );
    }
    // Heated floor representing server racks (y=0)
    floor
    {
        type wall;
        faces
        (
            (0 1 5 4)
        );
    }
    // Ceiling (y=3)
    ceiling
    {
        type wall;
        faces
        (
            (3 7 6 2)
        );
    }
    // Both side walls combined (z=0 and z=4)
    sideWalls
    {
        type wall;
        faces
        (
            (0 3 2 1)
            (4 5 6 7)
        );
    }
);

mergePatchPairs
(
);

What does this file define?

  • vertices: the 8 corners of the rectangular room, numbered 0 through 7. Vertices 0-3 are on the z=0 face, vertices 4-7 are on the z=4 face.
  • blocks: one hexahedral block connecting all 8 vertices, divided into 30 x 15 x 20 cells with uniform grading (no stretching).
  • boundary: five named patches that represent physical surfaces. The inlet and outlet are type "patch" (flow can cross them). The floor, ceiling, and side walls are type "wall" (solid surfaces).

Why these boundary patches?

Each patch represents a different physical role in the server room. The inlet is the CRAC unit supplying cool air. The outlet is where warm air exhausts. The floor represents heat coming off the server racks.

In the next step, you'll assign specific temperature and velocity values to each of these patches.

  • Save and exit nano by pressing **Ctrl+O**, **Enter**, then **Ctrl+X**.
  • Confirm the file was created by running:
ls system/

You should see blockMeshDict listed in the output.

File not appearing or content looks wrong?

If the file is missing, you may have exited nano without saving. Run nano system/blockMeshDict again and paste the content.

If you want to verify the content, run cat system/blockMeshDict to print the file to the terminal. Compare it against the code block above.

help me check my blockMeshDict file

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete system/blockMeshDict file for comparison:

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}

scale   1;

vertices
(
    (0 0 0)
    (6 0 0)
    (6 3 0)
    (0 3 0)
    (0 0 4)
    (6 0 4)
    (6 3 4)
    (0 3 4)
);

blocks
(
    hex (0 1 2 3 4 5 6 7) (30 15 20) simpleGrading (1 1 1)
);

edges
(
);

boundary
(
    inlet
    {
        type patch;
        faces
        (
            (0 4 7 3)
        );
    }
    outlet
    {
        type patch;
        faces
        (
            (1 2 6 5)
        );
    }
    floor
    {
        type wall;
        faces
        (
            (0 1 5 4)
        );
    }
    ceiling
    {
        type wall;
        faces
        (
            (3 7 6 2)
        );
    }
    sideWalls
    {
        type wall;
        faces
        (
            (0 3 2 1)
            (4 5 6 7)
        );
    }
);

mergePatchPairs
(
);
Generate and inspect the mesh

With the geometry defined, you can now generate the actual mesh. The blockMesh utility reads your blockMeshDict and creates the 3D cell structure that the solver will use.

  • Generate the mesh by running:
blockMesh

You should see output ending with End and no error messages. The output reports vertex and cell counts as it builds the mesh.

Seeing a blockMesh error?

If you see Cannot find file, make sure you're in the ~/serverRoom directory. Run pwd to check.

If you see a face ordering error, the vertex numbering in your boundary faces may be incorrect. Faces must be listed so that they point outward from the block. Compare your file against the double-check tab above.

help me fix my blockMesh error

  • Now verify the mesh quality by running:
checkMesh

Look for Mesh OK. at the end of the output. You should also see it report 9000 cells, 28,275 points, and 5 boundary patches.

What does checkMesh verify?

The checkMesh utility checks for problems that would cause the solver to fail or produce inaccurate results. It verifies cell shapes, face areas, and volume consistency.

For a simple rectangular mesh like this one, you should get a clean pass with no warnings. More complex geometries might show non-orthogonality or skewness warnings that need addressing.

checkMesh reports errors?

If checkMesh reports failed checks, your blockMeshDict likely has a typo in the vertex coordinates or face definitions. Open the file with nano system/blockMeshDict and compare it carefully against the double-check tab.

help me fix my mesh quality issues

Your server room geometry is now fully defined and meshed. Next up, you'll configure the physics: fluid properties, turbulence settings, and boundary conditions that bring this mesh to life as a real ventilation simulation.

Configure the Physics and Boundary Conditions

Your mesh is ready, but the solver needs to know what is flowing through that room and how it behaves at the boundaries.

In this step, you will define the fluid properties (air), select a turbulence model, and specify boundary conditions for every patch in your mesh. These boundary conditions tell the solver what happens at the inlet, outlet, floor, ceiling, and side walls.

In this step, get ready to:
  • Configure air properties and the k-epsilon turbulence model.
  • Define velocity and pressure boundary conditions for all patches.
  • Define temperature and turbulence boundary conditions to model the server room heat loads.
Set up fluid properties and turbulence model

The Boussinesq approximation treats air density as constant everywhere except in the buoyancy term, where small temperature differences drive the flow. This is valid for temperature differences below about 15 K for air, which our server room satisfies (291 K to 308 K).

  • Create the constant/transportProperties file by running this command in your terminal:
cat > constant/transportProperties << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      transportProperties;
}

transportModel  Newtonian;

nu              [0 2 -1 0 0 0 0] 1.5e-05;

beta            [0 0 0 -1 0 0 0] 3.33e-03;

TRef            300;

Pr              [0 0 0 0 0 0 0] 0.71;

Prt             [0 0 0 0 0 0 0] 0.85;
EOF

What do these properties mean?

  • nu is the kinematic viscosity of air at room temperature (1.5e-05 m2/s).
  • beta is the thermal expansion coefficient (3.33e-03 1/K). This controls how strongly temperature differences drive buoyancy.
  • TRef is the reference temperature (300 K) for the Boussinesq approximation.
  • Pr and Prt are the molecular and turbulent Prandtl numbers, controlling heat diffusion relative to momentum diffusion.
  • Confirm the file was created by running:
ls constant/transportProperties

You should see constant/transportProperties printed in the output.

Seeing 'No such file or directory'?

  • Make sure you are in the ~/serverRoom directory. Run cd ~/serverRoom if needed.
  • Check that you typed EOF on its own line at the end of the heredoc command. If the terminal is still waiting for input (showing >), type EOF and press Enter.

Help me troubleshoot my heredoc file creation

Next, the solver needs to know which turbulence model to use. The k-epsilon model is the standard choice for indoor ventilation CFD at this level.

  • Create the turbulence model configuration by running:
cat > constant/turbulenceProperties << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      turbulenceProperties;
}

simulationType  RAS;

RAS
{
    RASModel        kEpsilon;
    turbulence      on;
    printCoeffs     on;
}
EOF

What does this configure?

This selects Reynolds-Averaged Simulation (RAS) with the standard k-epsilon turbulence model. The k-epsilon model uses wall functions to approximate near-wall turbulence without requiring an extremely fine mesh near surfaces.

  • Verify both files exist by running:
ls constant/

You should see g, polyMesh, transportProperties, and turbulenceProperties listed.

Define velocity and pressure boundary conditions

Boundary conditions tell the solver what happens at each surface of your domain. For a ventilation simulation, you need to specify where air enters, where it leaves, and how it interacts with walls.

  • Create the velocity field file 0/U by running:
cat > 0/U << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volVectorField;
    object      U;
}

dimensions      [0 1 -1 0 0 0 0];

internalField   uniform (0 0 0);

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform (0.5 0 0);
    }
    outlet
    {
        type            inletOutlet;
        inletValue      uniform (0 0 0);
        value           uniform (0 0 0);
    }
    floor
    {
        type            noSlip;
    }
    ceiling
    {
        type            noSlip;
    }
    sideWalls
    {
        type            noSlip;
    }
}
EOF

What do these velocity boundary conditions mean?

  • inlet fixedValue (0.5 0 0): cool air enters at 0.5 m/s in the x-direction, simulating a CRAC unit supply.
  • outlet inletOutlet: allows air to flow freely out, but prevents backflow into the domain.
  • noSlip on walls: velocity is zero at all solid surfaces (floor, ceiling, side walls). This is the standard wall condition for viscous flow.
  • Confirm the file was created by running:
ls 0/U

You should see 0/U printed.

Terminal still showing the > prompt?

  • The > character means the heredoc is still open. Type EOF on its own line and press Enter to close it.
  • Make sure EOF has no leading spaces. It must be the only text on the line.

Help me fix my heredoc command

The pressure field in buoyancy-driven flow is split into two parts: p_rgh (pressure minus the hydrostatic component) and p (total pressure, derived from p_rgh).

  • Create the pressure field 0/p_rgh by running:
cat > 0/p_rgh << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      p_rgh;
}

dimensions      [0 2 -2 0 0 0 0];

internalField   uniform 0;

boundaryField
{
    inlet
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
    outlet
    {
        type            fixedValue;
        value           uniform 0;
    }
    floor
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
    ceiling
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
    sideWalls
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
}
EOF

What is fixedFluxPressure?

At walls and the inlet, pressure adjusts itself to maintain the specified velocity. The fixedFluxPressure type handles this automatically.

The outlet uses fixedValue 0 as the reference pressure for the entire domain.

  • Confirm the file exists by running:
ls 0/p_rgh

You should see 0/p_rgh in the output.

  • Create the total pressure field 0/p by running:
cat > 0/p << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      p;
}

dimensions      [0 2 -2 0 0 0 0];

internalField   uniform 0;

boundaryField
{
    inlet
    {
        type            calculated;
        value           uniform 0;
    }
    outlet
    {
        type            calculated;
        value           uniform 0;
    }
    floor
    {
        type            calculated;
        value           uniform 0;
    }
    ceiling
    {
        type            calculated;
        value           uniform 0;
    }
    sideWalls
    {
        type            calculated;
        value           uniform 0;
    }
}
EOF

Why is p set to calculated?

The total pressure p is automatically derived from p_rgh by adding back the hydrostatic component. You never need to set p directly.

  • Verify all three boundary condition files exist in the 0/ directory by running:
ls 0/

You should see U, p, and p_rgh listed.

Define temperature and turbulence boundary conditions

The temperature field is where you encode the actual server room scenario. Cool air enters at 291 K (18 degrees C, a typical CRAC supply temperature) and the floor radiates heat at 308 K (35 degrees C, representing server rack output).

  • Create the temperature field 0/T by running:
cat > 0/T << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      T;
}

dimensions      [0 0 0 1 0 0 0];

internalField   uniform 300;

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 291;
    }
    outlet
    {
        type            zeroGradient;
    }
    floor
    {
        type            fixedValue;
        value           uniform 308;
    }
    ceiling
    {
        type            zeroGradient;
    }
    sideWalls
    {
        type            zeroGradient;
    }
}
EOF

What do these temperature conditions represent?

  • inlet fixedValue 291 K: cool supply air from the CRAC unit at 18 degrees C (within ASHRAE recommended range of 18-27 degrees C).
  • floor fixedValue 308 K: the heated floor represents the combined heat output of server racks at 35 degrees C.
  • zeroGradient on outlet, ceiling, and sideWalls: these are adiabatic surfaces where temperature floats freely based on the flow.
  • Confirm the file was created by running:
ls 0/T

You should see 0/T printed.

File created but contents look wrong?

  • Run cat 0/T to inspect the file contents. Check that the inlet value is 291, the floor value is 308, and the internalField is 300.
  • If the content is garbled, delete the file with rm 0/T and re-run the heredoc command, making sure to copy the entire block including the closing EOF.

Help me check my temperature boundary conditions

The k-epsilon model requires initial and boundary values for turbulent kinetic energy (k), turbulent dissipation rate (epsilon), and turbulent thermal diffusivity (alphat).

  • Create the turbulent kinetic energy field 0/k by running:
cat > 0/k << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      k;
}

dimensions      [0 2 -2 0 0 0 0];

internalField   uniform 0.001;

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 0.001;
    }
    outlet
    {
        type            zeroGradient;
    }
    floor
    {
        type            kqRWallFunction;
        value           uniform 0.001;
    }
    ceiling
    {
        type            kqRWallFunction;
        value           uniform 0.001;
    }
    sideWalls
    {
        type            kqRWallFunction;
        value           uniform 0.001;
    }
}
EOF

What is kqRWallFunction?

Wall functions bridge the gap between the turbulence model and the wall surface without needing extremely fine mesh cells at the boundary. kqRWallFunction applies the appropriate wall treatment for turbulent kinetic energy.

  • Confirm the file was created by running:
ls 0/k

You should see 0/k listed.

  • Create the turbulent dissipation rate field 0/epsilon by running:
cat > 0/epsilon << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      epsilon;
}

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

internalField   uniform 0.001;

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 0.001;
    }
    outlet
    {
        type            zeroGradient;
    }
    floor
    {
        type            epsilonWallFunction;
        value           uniform 0.001;
    }
    ceiling
    {
        type            epsilonWallFunction;
        value           uniform 0.001;
    }
    sideWalls
    {
        type            epsilonWallFunction;
        value           uniform 0.001;
    }
}
EOF

What does this file control?

Epsilon represents the rate at which turbulent energy dissipates into heat. The epsilonWallFunction is the companion to kqRWallFunction, handling dissipation near walls.

  • Confirm the file was created by running:
ls 0/epsilon

You should see 0/epsilon listed.

  • Create the turbulent thermal diffusivity field 0/alphat by running:
cat > 0/alphat << 'EOF'
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      alphat;
}

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

internalField   uniform 0;

boundaryField
{
    inlet
    {
        type            calculated;
        value           uniform 0;
    }
    outlet
    {
        type            calculated;
        value           uniform 0;
    }
    floor
    {
        type            alphatJayatillekeWallFunction;
        Prt             0.85;
        value           uniform 0;
    }
    ceiling
    {
        type            alphatJayatillekeWallFunction;
        Prt             0.85;
        value           uniform 0;
    }
    sideWalls
    {
        type            alphatJayatillekeWallFunction;
        Prt             0.85;
        value           uniform 0;
    }
}
EOF

What is alphatJayatillekeWallFunction?

This wall function models how turbulence affects heat transfer near solid surfaces. The Prt 0.85 value is the turbulent Prandtl number, matching the value set in transportProperties.

  • Verify all boundary condition files exist by running:
ls 0/

You should see seven files: T, U, alphat, epsilon, k, p, and p_rgh.

Missing one or more files?

  • If a file is missing, re-run the heredoc command for that specific file. Check that you copied the entire block from cat through to EOF.
  • If a file has wrong contents, delete it with rm 0/filename and re-create it.
  • Make sure you are running all commands from the ~/serverRoom directory.

Help me check my OpenFOAM boundary condition files

✔️ Awesome, I've got everything!

Great. Make sure all nine files (two in constant/ and seven in 0/) are saved and you are ready for the next step.

ⓧ I'd like to double check the full code

Here are all the files you should have in constant/ and 0/ at this point. Use cat to inspect each file and compare.

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      transportProperties;
}

transportModel  Newtonian;

nu              [0 2 -1 0 0 0 0] 1.5e-05;

beta            [0 0 0 -1 0 0 0] 3.33e-03;

TRef            300;

Pr              [0 0 0 0 0 0 0] 0.71;

Prt             [0 0 0 0 0 0 0] 0.85;
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      turbulenceProperties;
}

simulationType  RAS;

RAS
{
    RASModel        kEpsilon;
    turbulence      on;
    printCoeffs     on;
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volVectorField;
    object      U;
}

dimensions      [0 1 -1 0 0 0 0];

internalField   uniform (0 0 0);

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform (0.5 0 0);
    }
    outlet
    {
        type            inletOutlet;
        inletValue      uniform (0 0 0);
        value           uniform (0 0 0);
    }
    floor
    {
        type            noSlip;
    }
    ceiling
    {
        type            noSlip;
    }
    sideWalls
    {
        type            noSlip;
    }
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      p_rgh;
}

dimensions      [0 2 -2 0 0 0 0];

internalField   uniform 0;

boundaryField
{
    inlet
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
    outlet
    {
        type            fixedValue;
        value           uniform 0;
    }
    floor
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
    ceiling
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
    sideWalls
    {
        type            fixedFluxPressure;
        value           uniform 0;
    }
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      p;
}

dimensions      [0 2 -2 0 0 0 0];

internalField   uniform 0;

boundaryField
{
    inlet
    {
        type            calculated;
        value           uniform 0;
    }
    outlet
    {
        type            calculated;
        value           uniform 0;
    }
    floor
    {
        type            calculated;
        value           uniform 0;
    }
    ceiling
    {
        type            calculated;
        value           uniform 0;
    }
    sideWalls
    {
        type            calculated;
        value           uniform 0;
    }
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      T;
}

dimensions      [0 0 0 1 0 0 0];

internalField   uniform 300;

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 291;
    }
    outlet
    {
        type            zeroGradient;
    }
    floor
    {
        type            fixedValue;
        value           uniform 308;
    }
    ceiling
    {
        type            zeroGradient;
    }
    sideWalls
    {
        type            zeroGradient;
    }
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      k;
}

dimensions      [0 2 -2 0 0 0 0];

internalField   uniform 0.001;

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 0.001;
    }
    outlet
    {
        type            zeroGradient;
    }
    floor
    {
        type            kqRWallFunction;
        value           uniform 0.001;
    }
    ceiling
    {
        type            kqRWallFunction;
        value           uniform 0.001;
    }
    sideWalls
    {
        type            kqRWallFunction;
        value           uniform 0.001;
    }
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      epsilon;
}

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

internalField   uniform 0.001;

boundaryField
{
    inlet
    {
        type            fixedValue;
        value           uniform 0.001;
    }
    outlet
    {
        type            zeroGradient;
    }
    floor
    {
        type            epsilonWallFunction;
        value           uniform 0.001;
    }
    ceiling
    {
        type            epsilonWallFunction;
        value           uniform 0.001;
    }
    sideWalls
    {
        type            epsilonWallFunction;
        value           uniform 0.001;
    }
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       volScalarField;
    object      alphat;
}

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

internalField   uniform 0;

boundaryField
{
    inlet
    {
        type            calculated;
        value           uniform 0;
    }
    outlet
    {
        type            calculated;
        value           uniform 0;
    }
    floor
    {
        type            alphatJayatillekeWallFunction;
        Prt             0.85;
        value           uniform 0;
    }
    ceiling
    {
        type            alphatJayatillekeWallFunction;
        Prt             0.85;
        value           uniform 0;
    }
    sideWalls
    {
        type            alphatJayatillekeWallFunction;
        Prt             0.85;
        value           uniform 0;
    }
}

Your physics and boundary conditions are fully configured. Next up, you will set up the solver controls and run the simulation to watch the airflow and temperature field develop.

Run the CFD Simulation

Your server room case now has a complete physical description. The mesh geometry, fluid properties, turbulence model, and all seven boundary condition files are defined and ready.

The solver still needs three configuration files in the system/ directory before it can run. These files control the numerical algorithms, discretization schemes, and convergence criteria that determine how OpenFOAM solves the governing equations.

In this step, get ready to:
  • Create controlDict, fvSchemes, and fvSolution to configure the solver.
  • Run buoyantBoussinesqSimpleFoam to compute the steady-state airflow and temperature field.
  • Verify the simulation converged by checking residual values and output directories.
Configure the solver settings

OpenFOAM's solver behaviour is controlled by three files in the system/ directory. Each file handles a different aspect of the numerical solution process.

  • Create system/controlDict by opening it in nano:
nano system/controlDict
  • Paste the following content into the editor:
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      controlDict;
}

application     buoyantBoussinesqSimpleFoam;

startFrom       startTime;

startTime       0;

stopAt          endTime;

endTime         1000;

deltaT          1;

writeControl    timeStep;

writeInterval   100;

purgeWrite      3;

writeFormat     ascii;

writePrecision  6;

writeCompression uncompressed;

timeFormat      general;

timePrecision   6;

runTimeModifiable true;

What does controlDict configure?

  • application tells OpenFOAM which solver to use. buoyantBoussinesqSimpleFoam handles buoyancy-driven incompressible flow using the Boussinesq approximation.
  • endTime 1000 caps the simulation at 1000 SIMPLE iterations. The solver can stop earlier if convergence targets are met.
  • writeInterval 100 saves results every 100 iterations, giving you snapshots of the solution as it evolves.
  • purgeWrite 3 keeps only the 3 most recent time directories to save disk space.
  • Press **Ctrl+O** then **Enter** to save the file.
  • Press **Ctrl+X** to exit nano.

New to nano?

nano is a simple terminal text editor. You can paste content with right-click (or **Ctrl+Shift+V** in most terminals). The commands at the bottom of the screen use ^ to mean the **Ctrl** key.

If you accidentally open the wrong file, press **Ctrl+X** and then **N** to exit without saving.

help me with nano in WSL

  • Create system/fvSchemes by opening it in nano:
nano system/fvSchemes
  • Paste the following content into the editor:
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSchemes;
}

ddtSchemes
{
    default         steadyState;
}

gradSchemes
{
    default         Gauss linear;
}

divSchemes
{
    default         none;
    div(phi,U)      bounded Gauss upwind;
    div(phi,T)      bounded Gauss upwind;
    div(phi,k)      bounded Gauss upwind;
    div(phi,epsilon) bounded Gauss upwind;
    div(phi,R)      bounded Gauss upwind;
    div(R)          Gauss linear;
    div((nuEff*dev2(T(grad(U))))) Gauss linear;
}

laplacianSchemes
{
    default         Gauss linear corrected;
}

interpolationSchemes
{
    default         linear;
}

snGradSchemes
{
    default         corrected;
}

What do these schemes control?

Discretization schemes convert the continuous governing equations into a system of algebraic equations that a computer can solve. Each scheme balances accuracy against numerical stability.

  • steadyState for ddtSchemes means there is no real time stepping. The solver iterates toward a steady solution.
  • bounded Gauss upwind for divergence schemes provides first-order accuracy with strong numerical stability. This is the standard starting point for SIMPLE-based solvers.
  • Gauss linear corrected for Laplacian schemes gives second-order accuracy for diffusion terms.
  • Save and exit nano (Ctrl+O, Enter, Ctrl+X).
  • Create system/fvSolution by opening it in nano:
nano system/fvSolution
  • Paste the following content into the editor:
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSolution;
}

solvers
{
    p_rgh
    {
        solver          PCG;
        preconditioner  DIC;
        tolerance       1e-08;
        relTol          0.01;
    }

    "(U|T|k|epsilon|R)"
    {
        solver          PBiCGStab;
        preconditioner  DILU;
        tolerance       1e-06;
        relTol          0.1;
    }
}

SIMPLE
{
    nNonOrthogonalCorrectors 0;
    pRefCell        0;
    pRefValue       0;

    residualControl
    {
        p_rgh           1e-04;
        U               1e-04;
        T               1e-04;
        "(k|epsilon)"   1e-04;
    }
}

relaxationFactors
{
    fields
    {
        p_rgh           0.3;
    }
    equations
    {
        U               0.7;
        T               0.5;
        "(k|epsilon|R)" 0.7;
    }
}

What does fvSolution control?

  • PCG (Preconditioned Conjugate Gradient) with DIC preconditioner solves the pressure equation, which produces a symmetric matrix.
  • PBiCGStab with DILU preconditioner solves velocity, temperature, and turbulence equations, which produce asymmetric matrices.
  • residualControl sets convergence targets at 1e-04 for all fields. The solver stops early if every residual drops below its target.
  • Relaxation factors control how aggressively each field updates between iterations. Lower values like 0.3 for p_rgh add stability. Higher values like 0.7 for U speed up convergence.
  • Save and exit nano (Ctrl+O, Enter, Ctrl+X).
  • Confirm all three solver files exist by running:
ls system/

You should see blockMeshDict, controlDict, fvSchemes, and fvSolution listed in the output.

Missing a file?

If a file is missing, you may have saved it to the wrong directory. Make sure you are in the ~/serverRoom directory when running nano system/controlDict. Check your current directory with pwd.

If nano did not save, make sure you pressed Ctrl+O (the letter O, not zero) followed by Enter before pressing Ctrl+X.

help me find my missing system files in OpenFOAM

✔️ Awesome, I've got all four files!

Double check you have saved all three new files before continuing.

ⓧ I'd like to double check the full code

Here are all three system files for reference. Compare your files against these.

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      controlDict;
}

application     buoyantBoussinesqSimpleFoam;

startFrom       startTime;

startTime       0;

stopAt          endTime;

endTime         1000;

deltaT          1;

writeControl    timeStep;

writeInterval   100;

purgeWrite      3;

writeFormat     ascii;

writePrecision  6;

writeCompression uncompressed;

timeFormat      general;

timePrecision   6;

runTimeModifiable true;
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSchemes;
}

ddtSchemes
{
    default         steadyState;
}

gradSchemes
{
    default         Gauss linear;
}

divSchemes
{
    default         none;
    div(phi,U)      bounded Gauss upwind;
    div(phi,T)      bounded Gauss upwind;
    div(phi,k)      bounded Gauss upwind;
    div(phi,epsilon) bounded Gauss upwind;
    div(phi,R)      bounded Gauss upwind;
    div(R)          Gauss linear;
    div((nuEff*dev2(T(grad(U))))) Gauss linear;
}

laplacianSchemes
{
    default         Gauss linear corrected;
}

interpolationSchemes
{
    default         linear;
}

snGradSchemes
{
    default         corrected;
}
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      fvSolution;
}

solvers
{
    p_rgh
    {
        solver          PCG;
        preconditioner  DIC;
        tolerance       1e-08;
        relTol          0.01;
    }

    "(U|T|k|epsilon|R)"
    {
        solver          PBiCGStab;
        preconditioner  DILU;
        tolerance       1e-06;
        relTol          0.1;
    }
}

SIMPLE
{
    nNonOrthogonalCorrectors 0;
    pRefCell        0;
    pRefValue       0;

    residualControl
    {
        p_rgh           1e-04;
        U               1e-04;
        T               1e-04;
        "(k|epsilon)"   1e-04;
    }
}

relaxationFactors
{
    fields
    {
        p_rgh           0.3;
    }
    equations
    {
        U               0.7;
        T               0.5;
        "(k|epsilon|R)" 0.7;
    }
}
Run the simulation

Everything is configured. The solver will iterate through the SIMPLE algorithm, solving for velocity, pressure, temperature, and turbulence fields at each step until the residuals drop below your 1e-04 targets (or until it reaches 1000 iterations).

  • Launch the solver by running this command:
buoyantBoussinesqSimpleFoam

What should I see?

The terminal will print output for each SIMPLE iteration. Each iteration shows residual values for Ux, Uy, Uz, T, p_rgh, k, and epsilon. These numbers should decrease as the solution converges.

On a typical laptop, the 9,000-cell mesh should finish in under 2 minutes. The solver will stop automatically when all residuals drop below 1e-04 or when it reaches iteration 1000.

Wait for the solver to finish. You will see a final summary line and the terminal prompt will return.

Solver crashes immediately?

  • If you see FOAM FATAL ERROR followed by a missing file message, double check that all files in 0/, constant/, and system/ exist. Run ls 0/ constant/ system/ to verify.
  • If you see a keyword not found error, check the file mentioned in the error message for typos. OpenFOAM dictionary keywords are case-sensitive.
  • If the solver diverges (residuals grow instead of shrink), check that your fvSchemes uses bounded Gauss upwind for all divergence terms. Upwind is the most stable scheme for initial runs.

help me debug my OpenFOAM solver error

Verify convergence

A converged solution means the solver has found a stable answer. You need to verify this before trusting the results for your report.

  • Scroll up in your terminal to find the final iteration output. All residuals (Ux, Uy, Uz, T, p_rgh, k, epsilon) should be at or below 1e-04.

What if residuals plateaued above 1e-04?

If residuals levelled off above 1e-04 and the solver ran all 1000 iterations, the solution has still reached a usable steady state. Note the final residual values for your report's methodology section.

For a coarser mesh like this one, slightly higher residuals are common and acceptable for learning purposes.

  • Confirm the solver wrote result directories by running:
ls

You should see numbered time directories (such as 100, 200, 300) alongside your 0, constant, and system directories. Since purgeWrite is set to 3, only the three most recent time directories are kept.

No time directories?

If you only see 0, constant, and system, the solver likely crashed before reaching iteration 100. Scroll up to find the error message. A common cause is a missing or malformed file in the 0/ directory.

help me figure out why buoyantBoussinesqSimpleFoam produced no output

Your simulation is complete and the results are sitting in those time directories. Next up, you will open the data in ParaView and create professional visualizations of the temperature and velocity fields.

Visualize Results in ParaView

Your simulation has converged and the results are sitting in time directories inside your case folder. Numbers in text files are useful, but a consulting deliverable needs visual evidence of airflow patterns and temperature distributions.

In this step, you will use ParaView to create professional visualizations of your CFD results. You will produce temperature contours, velocity vectors, streamlines, and a quantitative cross-section profile.

In this step, get ready to:
  • Open the OpenFOAM case in ParaView on Windows.
  • Create temperature contour, velocity vector, and streamline visualizations.
  • Extract a cross-section temperature profile showing thermal stratification.
Open the case in ParaView

ParaView cannot open OpenFOAM case directories directly. It needs a .foam file (an empty placeholder) in the case directory to know it is an OpenFOAM dataset.

  • In your Ubuntu terminal, make sure you are in your case directory by running:
cd ~/serverRoom
  • Create the empty .foam file by running:
touch serverRoom.foam
  • Confirm the file was created by running:
ls *.foam

You should see serverRoom.foam in the output.

Why an empty .foam file?

ParaView uses the file extension to determine which reader to use. The .foam extension triggers the OpenFOAM reader, which then scans the surrounding directory structure for constant/, system/, and time directories. The file itself can be completely empty.

Now you need to navigate to this file from Windows. The WSL filesystem is accessible from Windows File Explorer at a special network path.

  • Open **File Explorer** on Windows.
  • In the address bar at the top, type the following path and press **Enter**:
\\wsl$\Ubuntu-22.04\home\[[WSL_USERNAME="your Ubuntu username"]]\serverRoom
  • Right-click on serverRoom.foam.
  • Select **Open with**, then choose **ParaView** from the list.

ParaView not in the Open With list?

Click **Choose another app**, then browse to your ParaView installation folder (typically C:\Program Files\ParaView 6.0.1\bin\paraview.exe).

  • In ParaView, click the **Apply** button in the **Properties** panel on the left side.
  • In the toolbar at the top, find the time step dropdown. Select the latest time step (the highest number available).

You should see a 3D box representing your server room geometry rendered in the main viewport.

ParaView shows an empty viewport?

Make sure you clicked **Apply** after the case loaded. ParaView does not display data until you confirm with Apply.

If the viewport is still blank, check that the time step dropdown is set to the latest step (not 0). The initial time step contains only the boundary conditions, not the computed results.

help me load my OpenFOAM results in ParaView on Windows with WSL

Create temperature and velocity visualizations

A CFD report needs three types of visualization: a temperature contour to show where heat accumulates, velocity vectors to show airflow direction and strength, and streamlines to trace how supply air moves through the room.

Start with the temperature contour plot.

  • In the toolbar, find the **color by** dropdown (it may currently show Solid Color).
  • Change it to **T** to color the geometry by temperature.
  • Click the **Rescale to Custom Data Range** button (the icon with a small ruler and pencil next to the color legend).
  • Set the minimum to 291 and the maximum to 308. These match your inlet and floor boundary temperatures.
  • Click the **Edit Color Map** button (the colour palette icon next to the dropdown).
  • In the Color Map Editor, select **Cool to Warm** from the preset dropdown. This gives a blue-to-red thermal colour scheme.
  • Save this view as a screenshot: go to **File**, then **Save Screenshot**. Name it temperature_contour.png and save it to your Desktop.

You should see a 3D view of the room coloured from blue (291 K at the inlet) through to red (308 K near the floor).

What do the temperature contours tell you?

Look for thermal stratification. Warmer air (red/orange) rises toward the ceiling due to buoyancy, while cooler supply air (blue) remains lower. Hotspots near the floor indicate where server rack heat is strongest before being carried away by the airflow.

Next, create velocity vectors.

  • Make sure the serverRoom.foam source is selected in the **Pipeline Browser** on the left.
  • Go to **Filters** in the menu bar, then **Common**, then click **Glyph**.
  • In the Properties panel, set **Orientation Array** to **U** (velocity).
  • Set **Scale Mode** to **vector**.
  • Adjust the **Scale Factor** so that arrows are visible but do not overlap. Start with a value around 2 and increase or decrease until the arrows look clear.
  • Click **Apply**.
  • Change the **color by** dropdown to the magnitude of **U** so the arrows are coloured by velocity strength.
  • Save this view: **File**, then **Save Screenshot**. Name it velocity_vectors.png.

You should see arrows showing the direction and strength of airflow throughout the room.

Finally, create streamlines.

  • Click on the serverRoom.foam source in the **Pipeline Browser** (not the Glyph filter).
  • Go to **Filters**, then **Common**, then click **Stream Tracer**.
  • In the Properties panel, set **Seed Type** to **Point Cloud** or **Line**.
  • Position the seed points at the inlet face (x = 0). Set the **Point 1** coordinates to (0, 0, 0) and **Point 2** to (0, 3, 4) to span the inlet wall.
  • Click **Apply**.
  • Change the **color by** dropdown to **T** so the streamlines are coloured by temperature.
  • Save this view: **File**, then **Save Screenshot**. Name it streamlines.png.

You should see curved lines tracing how the cool supply air flows through the room, picking up heat as it passes over the floor and rising toward the ceiling.

What do streamlines reveal?

Streamlines show the path a massless particle would follow through the flow field. They reveal recirculation zones (where air loops back on itself) and stagnant regions (where streamlines are sparse). These are the areas a consultant would flag as potential hotspot risks.

Streamlines not appearing or showing errors?

Make sure you selected the serverRoom.foam source in the Pipeline Browser before applying the Stream Tracer filter. If you applied it on the Glyph filter, it will fail.

Also check that you are viewing the latest time step. Streamlines from the initial conditions (time 0) will not show meaningful flow.

help me get streamlines working in ParaView

Extract a cross-section temperature profile

Contour plots give a qualitative overview, but your report also needs quantitative data. A cross-section slice and a line plot will show the exact temperature variation from floor to ceiling at the room centre.

First, create a mid-plane slice.

  • Click on the serverRoom.foam source in the **Pipeline Browser**.
  • Go to **Filters**, then **Common**, then click **Slice**.
  • In the Properties panel, set the **Origin** to (3, 1.5, 2). This is the centre of the room.
  • Set the **Normal** to (0, 0, 1). This creates a slice perpendicular to the Z axis at z = 2 m (the room mid-plane).
  • Click **Apply**.
  • Change the **color by** dropdown to **T** to display the slice coloured by temperature.
  • Save this view: **File**, then **Save Screenshot**. Name it midplane_slice.png.

You should see a 2D cross-section of the room at its mid-plane, with the temperature distribution clearly visible as a colour gradient.

Now extract a quantitative temperature line plot.

  • With the Slice filter still selected in the Pipeline Browser, go to **Filters**, then **Data Analysis**, then click **Plot Over Line**.
  • In the Properties panel, set **Point 1** to (3, 0, 2). This is the floor at the room centre.
  • Set **Point 2** to (3, 3, 2). This is the ceiling directly above.
  • Click **Apply**.

ParaView switches to a line chart view. You should see a graph with height (arc length) on the x-axis and temperature (T) on the y-axis.

  • If multiple variables are plotted, uncheck all except **T** in the chart legend to show only temperature.
  • Save this chart: **File**, then **Save Screenshot**. Name it temperature_profile.png.

What does the temperature profile show?

The line plot shows thermal stratification. Temperature should be highest near the floor (around 308 K from server rack heat) and decrease with height as the cool supply air mixes in. A steep gradient near the floor indicates effective heat removal, while a flat profile higher up indicates good mixing.

This quantitative data is essential for your report. You can reference specific temperatures at specific heights, which is more convincing to clients than qualitative colour plots alone.

Plot Over Line shows a flat line or no data?

Check your point coordinates. Point 1 must be (3, 0, 2) and Point 2 must be (3, 3, 2). If the z-coordinate does not match the slice plane (z = 2), the line may fall outside the slice data.

Alternatively, apply the Plot Over Line filter directly on the serverRoom.foam source instead of on the Slice filter. This samples the full 3D field along the line regardless of slice position.

help me extract a temperature line plot in ParaView

You now have five professional visualizations saved as PNG files: temperature contour, velocity vectors, streamlines, mid-plane slice, and the quantitative temperature profile. Next up, you will compile these into a structured CFD technical report.

Write the CFD Technical Report

You have a converged simulation and a set of professional visualizations. The final deliverable for any CFD consultancy project is the technical report that communicates your findings to clients and colleagues.

In this step, you will write a structured CFD technical report following the format used by building services consultancies. The report documents your methodology, presents your results with the ParaView visualizations, and delivers actionable engineering recommendations.

In this step, get ready to:
  • Create a report document using the standard building services CFD consulting structure.
  • Document the methodology, boundary conditions, and computational domain.
  • Write engineering conclusions and recommendations based on your simulation results.
Structure the report using the consulting template

A CFD technical report in building services follows a standard structure that clients and engineering reviewers expect. This structure ensures your analysis is reproducible and your recommendations are clearly justified by the data.

  • Create a new document in your preferred tool (Word, Google Docs, or a Markdown file).
  • Copy the following report template into your document as your starting structure:
# CFD Ventilation Analysis: Server Room Airflow and Temperature Assessment

**Author:** [Your Name]
**Date:** [Date]
**Software:** OpenFOAM v2412, ParaView 6.0.1

---

## 1. Executive Summary

[One paragraph summarising the project scope, key findings, and primary recommendation. Write this last after completing the full analysis.]

## 2. Introduction and Objectives

This report presents the results of a Computational Fluid Dynamics (CFD) analysis conducted to evaluate the ventilation performance and thermal environment within a simplified server room. The objectives of this study are:

- Assess the airflow distribution from the supply inlet across the server room
- Evaluate the temperature distribution and identify potential hotspot locations
- Determine whether the proposed ventilation configuration maintains acceptable thermal conditions for server equipment
- Provide engineering recommendations for design improvement

## 3. Methodology

### 3.1 Governing Equations

The simulation employs the incompressible Navier-Stokes equations with the Boussinesq approximation for buoyancy effects. The Boussinesq approximation treats the fluid density as constant in all terms except the buoyancy term in the momentum equation, where density variations are linearly proportional to temperature differences:

rho = rho_ref * (1 - beta * (T - T_ref))

This approach is valid for temperature differences below approximately 15 K for air, which is satisfied in this case.

### 3.2 Solver

The buoyantBoussinesqSimpleFoam solver from OpenFOAM v2412 is used. This is a steady-state solver employing the SIMPLE (Semi-Implicit Method for Pressure-Linked Equations) algorithm for pressure-velocity coupling.

### 3.3 Turbulence Model

The standard k-epsilon turbulence model is used with standard wall functions (kqRWallFunction, epsilonWallFunction, alphatJayatillekeWallFunction) to approximate near-wall turbulence behaviour without requiring a fine boundary layer mesh.

## 4. Computational Domain and Mesh

### 4.1 Geometry

The server room is modelled as a rectangular enclosure with the following dimensions:
- Length (x): 6.0 m
- Height (y): 3.0 m
- Width (z): 4.0 m

The supply air inlet occupies the full x = 0 wall. The exhaust outlet occupies the full x = 6 m wall. The floor (y = 0) represents the heat output from server racks.

### 4.2 Mesh

A structured hexahedral mesh was generated using the blockMesh utility.
- Total cells: 9,000 (30 x 15 x 20)
- Cell type: Hexahedral
- Grading: Uniform (no stretching)

[Insert mesh quality metrics from checkMesh output here]

## 5. Boundary Conditions

[Insert a table with patches, boundary condition types, and values for U, T, and p_rgh. Reference the values from the case setup.]

## 6. Results and Discussion

### 6.1 Temperature Distribution

[Insert temperature contour screenshot. Describe the temperature field: where is the hottest region? Where is the coolest? Is thermal stratification visible?]

### 6.2 Velocity Field

[Insert velocity vector screenshot. Describe the flow pattern: does supply air reach all areas of the room? Are there recirculation zones or stagnant areas?]

### 6.3 Streamlines

[Insert streamline screenshot. Describe how the supply air flows through the room and how buoyancy affects the flow path.]

### 6.4 Cross-Section Temperature Profile

[Insert the mid-plane slice and/or the floor-to-ceiling temperature line plot. Describe the thermal stratification pattern: how does temperature vary with height?]

## 7. Conclusions and Recommendations

### 7.1 Key Findings

[Summarise 3-4 key findings from the analysis, e.g., maximum temperature, hotspot locations, effectiveness of ventilation]

### 7.2 Recommendations

[Provide 2-3 actionable engineering recommendations, e.g., repositioning exhaust, increasing supply velocity, adding ceiling-level extraction]

### 7.3 Limitations

- Simplified geometry: real server rooms contain rack obstructions, raised floors, and perforated tiles
- Uniform heat flux: actual server racks have non-uniform and variable heat output
- Steady-state assumption: transient effects such as cooling unit failure are not captured
- Mesh resolution: a mesh sensitivity study would be required for a production analysis

## 8. References

1. OpenFOAM v2412 Documentation. OpenCFD Ltd. https://www.openfoam.com
2. ASHRAE TC 9.9, Thermal Guidelines for Data Processing Environments, 5th Edition
3. Limane, A., Fellouah, H., and Galanis, N. (2015). Thermo-ventilation study by OpenFOAM of the airflow in a cavity with heated floor. Building Simulation, 8, 271-283.

What does this template cover?

The template follows the standard structure used by building services CFD consultancies. Each section serves a specific purpose:

  • The Executive Summary gives decision-makers the key finding in one paragraph.
  • The Methodology section makes your analysis reproducible by documenting solver choices and governing equations.
  • The Boundary Conditions table lets reviewers verify your setup at a glance.
  • The Limitations section is essential for professional credibility. It shows you understand where the model simplifications affect accuracy.
  • Fill in your name and today's date on the title page.
  • Leave the Executive Summary blank for now. You will write it last after completing all other sections.
Document methodology and results

The methodology and results sections form the technical core of your report. They show exactly what you simulated and what the simulation revealed.

  • In Section 3 (Methodology), verify that the template text accurately describes your setup. The template already documents the Boussinesq approximation, the SIMPLE algorithm, and the k-epsilon turbulence model.
  • In Section 4.2 (Mesh), replace the placeholder with your actual checkMesh output from Step 2. Include the number of cells, points, faces, and any quality metrics reported.

Finding your checkMesh output

If you did not save the output from Step 2, you can run checkMesh again in your Ubuntu terminal from the ~/serverRoom directory. The output is identical each time for the same mesh.

  • In Section 5 (Boundary Conditions), create a table with the following columns: Patch, Type (U), Value (U), Type (T), Value (T), Type (p_rgh), Value (p_rgh).
  • Fill in the table using the values from your case setup. Here are the values to include:
| Patch     | U type      | U value       | T type      | T value | p_rgh type         | p_rgh value |
|-----------|-------------|---------------|-------------|---------|--------------------|-----------|
| inlet     | fixedValue  | (0.5 0 0) m/s | fixedValue  | 291 K   | fixedFluxPressure  | 0         |
| outlet    | inletOutlet | (0 0 0) m/s   | zeroGradient| -       | fixedValue         | 0 Pa      |
| floor     | noSlip      | -             | fixedValue  | 308 K   | fixedFluxPressure  | 0         |
| ceiling   | noSlip      | -             | zeroGradient| -       | fixedFluxPressure  | 0         |
| sideWalls | noSlip      | -             | zeroGradient| -       | fixedFluxPressure  | 0         |

Why tabulate boundary conditions?

A boundary conditions table is standard practice in CFD reports. It lets reviewers verify your setup at a glance without reading through individual dictionary files. Clients who are not CFD specialists can also understand what physical scenario you modelled.

  • In Section 6 (Results and Discussion), insert each of your ParaView PNG screenshots into the corresponding subsection.
  • Below the temperature contour image (Section 6.1), describe what you observe. Note where the hottest region is located and whether thermal stratification is visible.
  • Below the velocity vector image (Section 6.2), describe the flow pattern. Note whether supply air reaches all areas of the room and identify any recirculation zones or stagnant areas.
  • Below the streamline image (Section 6.3), describe how the supply air flows through the room. Note how buoyancy affects the flow path.
  • Below the cross-section images (Section 6.4), insert both the mid-plane slice and the floor-to-ceiling line plot. Describe how temperature varies with height.

What should I look for in my results?

Your temperature contour should show cool air (around 291 K) entering from the inlet and warm air (approaching 308 K) accumulating near the floor and ceiling. The velocity vectors reveal how the jet from the inlet interacts with buoyancy forces.

The floor-to-ceiling line plot is particularly valuable. It quantifies the thermal stratification. You should see a clear temperature gradient from the heated floor upward.

Write engineering conclusions and recommendations

The conclusions and recommendations section is where your analysis delivers value to the client. A consultant does not just present data. They interpret it and propose design improvements.

  • In Section 7.1 (Key Findings), summarize 3-4 findings from your results. Include the maximum temperature observed, the location of hotspots relative to the exhaust, and the effectiveness of the ventilation pattern.
  • In Section 7.2 (Recommendations), write 2-3 actionable engineering recommendations based on your findings.

What makes a good engineering recommendation?

Good recommendations are specific, actionable, and tied directly to your simulation results. They tell the client what to change and why.

For example: "The simulation indicates thermal stratification with temperatures reaching X K near the ceiling. Repositioning the exhaust outlet to the ceiling would improve hot air extraction." Compare this to a vague recommendation like "improve ventilation" which gives the client nothing to act on.

  • Review the Limitations section (7.3). The template already includes four standard limitations. Add any additional limitations you noticed during your analysis.
  • Verify the References section (Section 8). The template includes three references: the OpenFOAM v2412 documentation, ASHRAE TC 9.9 thermal guidelines for data centres, and the Limane et al. (2015) paper on thermo-ventilation with OpenFOAM.
  • Finally, return to Section 1 (Executive Summary) and write one paragraph summarizing: what you simulated, your key finding, and your primary recommendation.

Write the Executive Summary last

The Executive Summary is always written after the full analysis is complete. It distills the entire report into one paragraph that a project manager or client can read in 30 seconds to understand the outcome.

  • Save your completed report document.
  • Review the document from start to finish. Confirm that every placeholder section has been filled in with your actual data, screenshots, and analysis.

Report feeling incomplete?

Check that you have inserted all five ParaView screenshots (temperature contour, velocity vectors, streamlines, mid-plane slice, and floor-to-ceiling line plot). Each image should have a paragraph below it describing what it shows.

If you are unsure what to write in the results discussion, describe what you see in plain language first. Where is the hot air? Where is the cool air? Does the airflow pattern make physical sense given the inlet and outlet positions?

help me interpret my CFD results for the server room report

Your CFD technical report is complete. This is the exact deliverable format that a Graduate CFD Consultant at a building services consultancy would produce. Next up, the Secret Mission challenges you to run a parametric study comparing two design alternatives.

Secret mission

Parametric Study with Different Supply Temperatures

Real CFD consultants never run just one simulation. They compare design alternatives to find the best solution. In this secret mission, you will run a second simulation with a warmer supply air temperature and add a professional design comparison section to your report.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine, so there are no ongoing cloud costs. Decide whether to keep your resources installed, pause them to free up disk space, or delete them entirely.

Resources you used:

  • WSL2 with Ubuntu 22.04 (includes OpenFOAM v2412 installation).
  • ParaView 6.0.1 (Windows native installation).
  • The serverRoom case directory (and serverRoom_warm if you completed the Secret Mission).
  • Your CFD technical report document.

Keep everything running

No action needed. Choose this if you plan to continue experimenting with OpenFOAM, refining your mesh, or running additional simulations.

  • Your WSL2 Ubuntu environment, OpenFOAM, and ParaView all remain installed and ready to use.
  • Your serverRoom case directory stays in your WSL home folder at ~/serverRoom.
  • You can re-run the simulation or modify boundary conditions at any time.

Pause - I'll come back to this later

Shut down WSL to free up memory while keeping all your files and installations intact.

  • Open PowerShell and run wsl --shutdown to stop the WSL2 virtual machine. This frees up the RAM that Ubuntu was using.
  • Your OpenFOAM installation, case files, and simulation results all remain on disk. When you open Ubuntu again, everything will be exactly as you left it.
  • ParaView stays installed on Windows. No action needed for it.

Delete - I don't want to use this again

Remove all project resources and installations to start fresh.

  • To delete just the simulation files, open Ubuntu and run rm -rf ~/serverRoom ~/serverRoom_warm.
  • To uninstall OpenFOAM from Ubuntu, run sudo apt-get remove --purge openfoam2412-default.
  • To remove the entire WSL Ubuntu distribution, open PowerShell and run wsl --unregister Ubuntu-22.04. This deletes Ubuntu and everything inside it, including OpenFOAM and all case files.
  • To uninstall ParaView, open Settings on Windows.
  • Select Apps, then Apps & features.
  • Search for ParaView, click it, and select Uninstall.
  • Delete your report document manually if you no longer need it.

That's a Wrap!

That's a Wrap!

Nice work! You have completed a full CFD ventilation analysis workflow, from setting up OpenFOAM on Windows through to delivering a professional technical report.

You've learned how to:

  • Configured and ran a buoyancy-driven CFD simulation using OpenFOAM's buoyantBoussinesqSimpleFoam solver with the Boussinesq approximation and k-epsilon turbulence model for indoor ventilation analysis.
  • Created professional-quality visualizations in ParaView including temperature contours, velocity vectors, streamlines, and quantitative cross-section profiles.
  • Written a consulting-grade CFD technical report with methodology, boundary condition tables, results discussion, and actionable engineering recommendations.
  • Secret Mission: Conducted a parametric study comparing two supply air temperatures and presented comparative results with design recommendations.

Ready to quiz yourself?