Turbulence Guide

OpenFOAM Wall Functions: Complete Guide

Wall functions are boundary conditions for turbulence quantities (k, epsilon, omega, nut) that model the near-wall region without resolving it directly. Choosing the right wall treatment — and the right y+ — is one of the most impactful decisions in any RANS simulation.

By CFDpilot · Updated April 2026

Wall functions vs. low-Reynolds wall treatment

There are two approaches to modelling the boundary layer in RANS:

The critical constraint: do not mix them. If you use wall functions, your first cell must be at y+ 30–300. If you use low-Re treatment, you need y+ ≈ 1. A mesh with y+ = 5 is in the buffer layer — both approaches fail there.

Computing the first-cell height for a target y+

The non-dimensional wall distance y+ is defined as:

y+ = y * u_tau / nu

where:
  y     = distance from wall to first cell centroid [m]
  u_tau = friction velocity = sqrt(tau_w / rho)  [m/s]
  nu    = kinematic viscosity [m²/s]

A practical estimate for the friction velocity in turbulent boundary layers is u_tau ≈ 0.05 * U_ref. For a more precise estimate, use the Blasius correlation for flat-plate flows or the Moody chart for pipe flow. The required first-cell height is then:

# Target y+ = 50, U_ref = 10 m/s, air (nu = 1.5e-5 m²/s)
u_tau  ≈ 0.05 * 10 = 0.5 m/s
y      = y+ * nu / u_tau = 50 * 1.5e-5 / 0.5 = 1.5e-3 m

# Target y+ = 1 (low-Re, resolving viscous sublayer)
y      = 1 * 1.5e-5 / 0.5 = 3.0e-5 m  (30 microns)

This calculation gives a starting point. Always verify by running the simulation and checking actual y+ values using the yPlus function object.

Checking y+ in your simulation

Add this to your controlDict functions block to compute y+ at runtime:

functions
{
    yPlus
    {
        type        yPlus;
        libs        (fieldFunctionObjects);
        writeControl writeTime;
    }
}

After running, open postProcessing/yPlus/ and check the min/max values. Target: y+ max < 300, y+ min > 30 for wall functions.

You can also post-process y+ directly after a completed steady-state run:

# Post-process y+ from the final time step
simpleFoam -postProcess -func yPlus

The resulting yPlus field can be visualised in ParaView — look for patches where y+ falls below 30 or above 300 and adjust your mesh grading accordingly.

k-epsilon wall functions

Standard configuration for wall patches in 0/k, 0/epsilon, 0/nut:

// 0/k
wall
{
    type        kqRWallFunction;
    value       uniform 0;
}

// 0/epsilon
wall
{
    type        epsilonWallFunction;
    value       uniform 0;
}

// 0/nut
wall
{
    type        nutkWallFunction;
    value       uniform 0;
}

The kqRWallFunction type applies a Neumann (zero-gradient) condition on k, leaving k free to be determined by the turbulence model in the near-wall cell. The epsilonWallFunction imposes the production-equals-dissipation equilibrium assumption from the log-law, computing epsilon from the local k and cell height.

k-omega SST wall functions

k-ω SST has a built-in blending between log-law and viscous sublayer. It handles both y+ ≈ 1 and y+ 30–300, but the recommended practice is to target one or the other consistently:

// 0/k — same for both y+ regimes
wall
{
    type        kqRWallFunction;
    value       uniform 0;
}

// 0/omega
wall
{
    type        omegaWallFunction;
    value       uniform 0;
}

// 0/nut — for high-Re (y+ 30-300)
wall
{
    type        nutkWallFunction;
    value       uniform 0;
}

// 0/nut — for low-Re (y+ ~1)
wall
{
    type        nutLowReWallFunction;
    value       uniform 0;
}

The omegaWallFunction in OpenFOAM uses Menter's blending: it computes omega from both the viscous sublayer formula and the log-law, then takes the maximum. This makes it robust across y+ regimes, but does not eliminate the accuracy penalty of sitting in the buffer layer.

Spalart-Allmaras wall treatment

SA solves a single transport equation for modified eddy viscosity nuTilda. At walls:

// 0/nuTilda
wall
{
    type        fixedValue;
    value       uniform 0;
}

// 0/nut
wall
{
    type        fixedValue;
    value       uniform 0;
}

SA is designed for low-Re wall treatment (y+ ≈ 1). Using it with y+ 30–300 degrades accuracy significantly.

Wall functions for thermal simulations

When running buoyantSimpleFoam or conjugate heat transfer cases, temperature also requires a wall function. The standard choice is alphatJayatillekeWallFunction for turbulent thermal diffusivity:

// 0/alphat — turbulent thermal diffusivity
wall
{
    type        compressible::alphatJayatillekeWallFunction;
    Prt         0.85;        // turbulent Prandtl number
    value       uniform 0;
}

// 0/T — temperature at wall (isothermal)
heatedWall
{
    type        fixedValue;
    value       uniform 350;   // 350 K
}

// 0/T — adiabatic wall (zero heat flux)
adiabaticWall
{
    type        zeroGradient;
}

The Jayatilleke function models the thermal sub-layer using the universal temperature profile, analogous to how velocity wall functions model the velocity sub-layer. The turbulent Prandtl number Prt is typically 0.85 for air and most gases.

Rough wall functions

For surfaces with significant roughness (sand-grain roughness height Ks), OpenFOAM provides roughness-modified wall functions. These shift the log-law downward based on the roughness Reynolds number:

// 0/nut — rough wall
roughWall
{
    type        nutkRoughWallFunction;
    Ks          uniform 5e-4;   // sand-grain roughness height [m]
    Cs          uniform 0.5;    // roughness constant (0.5 for sand-grain)
    value       uniform 0;
}

The roughness Reynolds number Ks+ = Ks * u_tau / nu determines the roughness regime: hydraulically smooth for Ks+ < 5, fully rough for Ks+ > 70. Ensure y+ > Ks+ to avoid the roughness elements extending beyond the first cell.

Blended wall functions (OpenFOAM v2106+)

Recent OpenFOAM versions introduced automatically-blended wall functions that reduce sensitivity to y+ placement. The nutBlendedWallFunction blends between viscous and log-law formulations continuously:

// 0/nut — blended, less sensitive to y+ in 5-30 range
wall
{
    type        nutBlendedWallFunction;
    value       uniform 0;
}

While these reduce the sensitivity to buffer-layer y+ values, they do not fully replace the need for a properly designed mesh. The blended functions are particularly useful during early-stage simulations where the exact y+ distribution is not yet known.

Common mistakes

Get the right wall functions for your y+ — free

Upload your case and CFDpilot checks your y+ range and recommends the correct wall function for each turbulence model.

Check my wall treatment →
Official documentation

Frequently Asked Questions

What y+ value should I use with OpenFOAM wall functions?

For standard wall functions (nutkWallFunction, epsilonWallFunction), target y+ between 30 and 300. The first cell centroid must sit in the log-law region. Values below 30 fall into the buffer layer where wall functions are inaccurate. Values above 300 push beyond the range where the log-law holds for most turbulent flows.

What is the difference between nutkWallFunction and nutLowReWallFunction?

nutkWallFunction computes turbulent viscosity from the log-law and is designed for meshes with y+ between 30 and 300. nutLowReWallFunction is for fully resolved boundary layers with y+ near 1, where the viscous sublayer is explicitly captured by the mesh. Using nutkWallFunction on a y+ = 1 mesh gives incorrect nut values at the wall.

Can k-omega SST work with both high and low y+?

Yes — k-omega SST blends between the viscous sublayer and log-law formulations. However, target one regime consistently. The buffer layer (y+ 5 to 30) should be avoided regardless of the turbulence model. The omegaWallFunction in OpenFOAM uses Menter's blending to handle intermediate y+ values, but accuracy is still degraded in the buffer layer.

Why does my y+ vary significantly across the wall patch?

y+ is a local quantity that depends on local wall shear stress, which varies across the geometry. A uniform first-cell height will produce non-uniform y+. Near stagnation points, y+ will be very low; near high-shear regions (e.g., throat of a nozzle), y+ will be higher. Check y+ distribution in ParaView and identify whether the outlier regions are critical for your quantities of interest.

How do I set up wall functions for a rough surface in OpenFOAM?

Use nutkRoughWallFunction with the Ks (sand-grain roughness height) and Cs (roughness constant, typically 0.5) parameters. Ensure the first-cell y+ is greater than the roughness Reynolds number Ks+ = Ks × u_tau / nu to avoid the roughness extending beyond the first cell height.

Do I need wall functions for the velocity field U?

No. The velocity boundary condition at a wall is always noSlip (or fixedValue with zero velocity). Wall functions apply only to turbulence quantities: k, epsilon, omega, and nut. The velocity gradient at the wall is handled implicitly through the turbulent viscosity computed by the wall function.