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.
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.
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.
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.
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).
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.
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.
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
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.
Two additional commonly used function objects for aerodynamic and turbulence post-processing:
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.
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).
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.
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.
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.
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.
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.
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.
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.
Upload your case and CFDpilot checks your controlDict function objects, field names, and output settings.
Review my setup →