Post-Processing Guide

OpenFOAM Function Objects: Forces, Probes, yPlus and Residuals

Function objects are OpenFOAM's built-in post-processing and monitoring system. They run during the simulation — or applied afterward with postProcess — to compute forces, sample field values at probes, compute time averages, check y+, and monitor convergence. This guide covers the most useful function objects with complete syntax examples.

By CFDpilot · Updated April 2026

1. The functions{} block in controlDict

All function objects are defined inside the functions{} subdictionary of system/controlDict:

functions
{
    myFunctionObject1
    {
        type            probes;
        libs            (sampling);
        // ... settings
    }

    myFunctionObject2
    {
        type            forceCoeffs;
        libs            (forces);
        // ... settings
    }
}

Each function object has a user-defined name (arbitrary), a type that identifies which function object class to load, and a libs list that tells OpenFOAM which shared library contains that class.

Function objects can also be placed in a separate file:

functions
{
    #includeFunc forceCoeffs
    #include "system/myProbes"
}

The #includeFunc directive loads a named function object from the OpenFOAM function object library with default settings, which you can then override with additional entries.

2. writeControl and writeInterval

Every function object has its own output frequency, independent of the main solver write frequency. This lets you sample at high frequency for probes while writing full field snapshots less often.

myProbes
{
    type            probes;
    libs            (sampling);

    writeControl    timeStep;    // or runTime, adjustableRunTime
    writeInterval   10;          // every 10 time steps

    // ... probe settings
}

writeControl timeStep with a small writeInterval is appropriate for probes monitoring fast-changing quantities. For forces on a steady-state run, writeControl timeStep with writeInterval 1 gives you every iteration. For LES averaging, use writeControl writeTime to synchronize with the main write frequency.

3. forceCoeffs: computing drag and lift

The forceCoeffs function object computes lift, drag, and moment coefficients on specified patches throughout the simulation:

forceCoeffs1
{
    type            forceCoeffs;
    libs            (forces);

    writeControl    timeStep;
    writeInterval   1;

    patches         ( wing fuselage );   // surface patches

    rho             rhoInf;
    rhoInf          1.225;               // kg/m^3 for incompressible
    Uref            30.0;                // m/s reference velocity
    Aref            0.5;                 // m^2 reference area
    lRef            0.2;                 // m reference length (for moments)

    CofR            ( 0.25 0 0 );       // centre of rotation for moments

    liftDir         ( 0 1 0 );           // lift direction (y for 2D airfoil)
    dragDir         ( 1 0 0 );           // drag direction (x)
    pitchAxis       ( 0 0 1 );           // moment axis (z)
}

Output is written to postProcessing/forceCoeffs1/0/forceCoeffs.dat. The file contains columns: Time, Cm, Cd, Cl, Cl(f), Cl(r). For incompressible solvers, set rho rhoInf and specify rhoInf manually. For compressible solvers, set rho rho to use the computed density field.

forces: raw force components

To get raw force vectors (not coefficients), use the forces type instead:

forces1
{
    type            forces;
    libs            (forces);
    patches         ( body );
    rho             rhoInf;
    rhoInf          1.0;
    CofR            ( 0 0 0 );
    writeControl    timeStep;
    writeInterval   1;
}

Output includes viscous and pressure contributions separately, which is useful for diagnosing the source of drag (skin friction vs pressure drag).

4. probes: monitoring point values

The probes function object samples field values at specified spatial locations during the simulation:

probes1
{
    type            probes;
    libs            (sampling);

    writeControl    timeStep;
    writeInterval   1;

    probeLocations
    (
        ( 0.1  0.0  0.0 )    // downstream of body
        ( 0.5  0.1  0.0 )    // in wake
        ( 1.0  0.0  0.0 )    // far wake
    );

    fields ( U p k );
}

Output files are written to postProcessing/probes1/0/U, postProcessing/probes1/0/p, etc. Each file has one column per probe location, with time as the first column. These files can be directly plotted in gnuplot or Python to monitor quantities during the run.

If a probe location falls outside the mesh (e.g., inside a solid body), OpenFOAM will print a warning and assign the value from the nearest boundary face. Verify probe placement in ParaView before running.

5. fieldAverage: time-averaging for LES and unsteady RANS

fieldAverage computes running time averages of fields — essential for LES post-processing and useful for monitoring convergence of unsteady RANS:

fieldAverage1
{
    type            fieldAverage;
    libs            (fieldFunctionObjects);

    writeControl    writeTime;
    timeStart       2.0;        // skip initial transient
    cleanRestart    no;

    fields
    (
        U
        {
            mean        on;
            prime2Mean  on;      // Reynolds stresses UPrime2Mean
            base        time;
        }
        p
        {
            mean        on;
            prime2Mean  on;
            base        time;
        }
        k
        {
            mean        on;
            prime2Mean  off;
            base        time;
        }
    );
}

This produces averaged fields named UMean, pMean, UPrime2Mean (the Reynolds stress tensor as a symmetric tensor field) in each written time directory. Use timeStart to exclude the initial transient from the average.

cleanRestart no preserves the accumulated average when the simulation is restarted — set to yes only if you want to reset the averaging window on restart.

6. yPlus: verifying wall resolution

The yPlus function object computes the dimensionless wall distance y+ at every wall cell and writes it as a field:

yPlus1
{
    type            yPlus;
    libs            (fieldFunctionObjects);

    writeControl    writeTime;
    patches         ( wall lowerWall upperWall );
}

Output is written to postProcessing/yPlus1/latestTime/yPlus.dat with minimum, maximum, and average y+ per patch, and as a full field yPlus that can be visualized in ParaView.

For standard wall functions (k-omega SST, k-epsilon), target y+ between 30 and 300. For low-Reynolds wall treatment or LES wall-resolved runs, target y+ < 1. Values outside these ranges indicate the first cell layer needs adjustment.

You can also run yPlus as a post-processing step without modifying controlDict:

postProcess -func yPlus -latestTime

7. residuals function object

The residuals function object writes per-field residuals to a file during the simulation — much easier to parse than filtering the main log:

residuals1
{
    type            residuals;
    libs            (utilityFunctionObjects);

    writeControl    timeStep;
    writeInterval   1;

    fields          ( p U k epsilon );
}

Output is written to postProcessing/residuals1/0/residuals.dat with columns for time/iteration and the initial residual of each specified field. This file can be plotted directly to generate convergence history graphs without log file parsing.

For steady-state cases, plot the residuals file to see whether all fields have converged by 3–5 orders of magnitude. If p residual plateaus while U is still dropping, the pressure solver tolerance may be too loose.

8. wallShearStress and turbulenceFields

Two additional commonly used function objects for aerodynamic and turbulence post-processing:

wallShearStress

wallShearStress1
{
    type            wallShearStress;
    libs            (fieldFunctionObjects);
    patches         ( wall );
    writeControl    writeTime;
}

Computes the wall shear stress vector field on specified patches. Useful for identifying separation regions (where shear stress reverses sign) and for computing skin friction coefficients.

turbulenceFields

turbulenceFields1
{
    type            turbulenceFields;
    libs            (fieldFunctionObjects);
    writeControl    writeTime;
    fields          ( k epsilon nut L I );
}

Computes and writes derived turbulence quantities: turbulent kinetic energy k, dissipation rate epsilon or omega, turbulent viscosity nut, turbulent length scale L, and turbulence intensity I. Useful when these fields are not primary solver variables (e.g., in algebraic turbulence models).

9. Running function objects in post-processing mode

All function objects can be applied to existing time directories without re-running the simulation using the postProcess utility:

# Process all time directories
postProcess -func forceCoeffs

# Process only the latest time
postProcess -func yPlus -latestTime

# Process a specific time range
postProcess -func fieldAverage -time "1:5"

# Process using a named function object from controlDict
postProcess -func residuals1

This is particularly useful for functions you forgot to add during the run, or for applying new analysis (e.g., computing turbulent length scales) to an already-completed simulation without repeating the expensive solver step.

FAQ

Where do function objects go in an OpenFOAM case?

Function objects are defined in the functions{} subdictionary of system/controlDict. They can also be placed in a separate file in the system/ directory and included with #includeFunc or #include directives. This keeps controlDict manageable when you have many function objects.

How do I compute drag and lift forces in OpenFOAM?

Use the forceCoeffs function object in controlDict. Specify the patches (your body surface), the reference area, velocity, density, and lift/drag directions. Results are written to postProcessing/forceCoeffs/0/forceCoeffs.dat and update every iteration.

How do I monitor point values during an OpenFOAM simulation?

Use the probes function object. Specify probe locations as a list of coordinates and the fields to sample. Values are written every writeInterval to postProcessing/probes/0/fieldName. You can watch these files update in real time with a Python script or gnuplot.

How do I compute yPlus in OpenFOAM post-processing?

Use the yPlus function object in controlDict with the wall patches specified. It writes y+ per patch (min/max/average) and as a full field. Alternatively run postProcess -func yPlus -latestTime after the simulation without changing controlDict.

How do I compute time-averaged fields in OpenFOAM?

Use the fieldAverage function object. Specify fields with mean on and prime2Mean on for Reynolds stresses. Set timeStart to skip the initial transient period. Averaged fields are written alongside instantaneous fields at each write time.

Can I run function objects without restarting the simulation?

Yes. Use postProcess -func functionObjectName to apply function objects to existing time directories. This runs the function object on all saved time steps without repeating the simulation. Use -latestTime to process only the last saved time.

Official documentation

Get your function objects setup reviewed — free

Upload your case and CFDpilot checks your controlDict function objects, field names, and output settings.

Review my setup →