OpenFOAM Post-Processing — Function Objects and Field Analysis
#+CATEGORY: openfoam # :PROPERTIES: # :ID: uuid-openfoam-postprocessing # :END:
OpenFOAM Post-Processing :: Function Objects, sampling, and field analysis
This note documents OpenFOAM's post-processing framework: the functionObjects system, the postProcess utility, and integration with ParaView. This is the practical counterpart to Turbulence Models (for Q-criterion and turbulence visualisation) and OpenFOAM Solver Selection (for force coefficient computation during simulation).
OpenFOAM's post-processing philosophy is "continuous output": rather than writing all field data at every timestep and analysing it later (which produces massive files), functionObjects compute quantities on-the-fly and write only the quantities of interest to postProcessing/. This reduces I/O by 10–100× compared to writing full field snapshots.
**Table of Contents**
- Function Objects :: In-situ post-processing framework
- fieldValues :: Field sampling (cell, face, point)
- Sampling and Probes :: Line, plane, and point probes
- #forces-and-forceCoeffs[forces and forceCoeffs]] :: Drag, lift, moment computation
- postProcess utility :: Post-simulation analysis
- foamToVTK and ParaView :: VTK export and ParaView integration
- Python automation :: Scripting post-processing
- See Also
- References
Function Objects :: In-Situ Post-Processing Framework
FunctionObjects are OpenFOAM's in-situ post-processing system. They are specified in system/controlDict and/or system/functionObjects and execute at each write step. Every functionObject is a shared library (lib*.so) registered with OpenFOAM's functionObjectRegistry.
/* system/controlDict */
functions
{
// Example: fieldValues - point/sample/line probes
fieldValues
{
type fieldValues;
libs ("libfieldFunctionObjects.so");
writeControl timeStep;
writeInterval 100;
fields (p U rho T k omega);
// Point probes
probe1
{
type probes;
libs ("libfieldFunctionObjects.so");
fields (p U);
probeLocations ((0.5 0.0 0.0));
}
// Line sampling
line1
{
type sample;
libs ("libfieldFunctionObjects.so");
fields (p U);
application sample;
libs ("libsampling.so");
samplingPlane uniform (0 0 0) (0 1 0) 10; // position, normal, cells
}
}
// Example: forceCoeffs for drag/lift
forceCoeffs
{
type forceCoeffs;
libs ("libforces.so");
patchNames (wing);
liftDir (0 1 0); // upward direction
dragDir (1 0 0); // flow direction
rhoName rhoInf; // incompressible: constant density
rhoInf 1000; // density
CofR (0 0 0); // center of rotation for moment
pitchAxis (0 0 1);
referenceArea 1.0; // reference area (wing planform area)
Pname p; // pressure field name
Uname U; // velocity field name
}
// Example: residuals monitoring
residuals
{
type residuals;
libs ("libsolutionFunctionObjects.so");
printCoeffs true;
}
// Example: field average for turbulence statistics
fieldAverage
{
type fluidMotion; // not standard - see fieldAverage
libs ("libfieldFunctionObjects.so");
fields
(
p
{
mean on;
prime2Mean on;
base time;
}
U
{
mean on;
prime2Mean on;
base time;
}
k
{
mean on;
base time;
}
);
}
}
Available functionObject types:
| Type | Library | Purpose |
| ------ | --------- | --------- |
| residuals | libsolutionFunctionObjects.so | Residuals per field per timestep |
| force | libforces.so | Integral forces on patches (N) |
| forceCoeffs | libforces.so | Non-dimensional force coefficients |
| probes | libfieldFunctionObjects.so | Point probes (time series) |
| sample | libfieldFunctionObjects.so | Line/plane/surface sampling |
| fieldValues | libfieldFunctionObjects.so | Cell/face/point sampling |
| streamLine | libfieldFunctionObjects.so | Streamline tracing |
| contour | libfieldFunctionObjects.so | Contour generation |
| cut | libfieldFunctionObjects.so | Slicing planes |
| waveProbe | libfieldFunctionObjects.so | Free surface probe (VOF) |
| coordinateSystem | libfieldFunctionObjects.so | Coordinate transform |
| cellSet | libfieldFunctionObjects.so | Cell selection and modification |
| faceSet | libfieldFunctionObjects.so | Face selection and modification |
The residuals functionObject is the OpenFOAM equivalent of Fluent's Residual Monitors — it prints the L2 norm of each equation residual at each timestep. This is the first indicator of whether your simulation is converging or diverging.
The force and forceCoeffs functionObjects are the OpenFOAM equivalent of Fluent's Surface Integrals → Force. They integrate pressure and viscous stress over specified patches and compute resultant forces. The forceCoeffs variant also computes non-dimensional coefficients:
- Drag coefficient: =C_D = F_D / (0.5 \rho U^2 A)/
- Lift coefficient: =C_L = F_L / (0.5 \rho U^2 A)/
- Moment coefficient: =C_M = M / (0.5 \rho U^2 A L)/
where A is the reference area and L is the reference length. The choice of reference area and length directly affects the coefficient values — always document the reference values in any report. Fluent achieves the same result through Reports → Forces with user-defined reference values.
fieldValues :: Point, Surface, and Cell Sampling
The fieldValues functionObjects can sample data at specific locations or over specific patches:
fieldValues
{
type fieldValues;
libs ("libfieldFunctionObjects.so");
// Volume averages
volumeAvg
{
type volFieldValue;
libs ("libfieldFunctionObjects.so");
log true;
operation volAverage; // or: volAverage, volIntegrate, min, max
regionType cellZone;
name myCellZone;
fields (p U k omega);
}
// Area averages
surfaceAvg
{
type surfaceFieldValue;
libs ("libfieldFunctionObjects.so");
log true;
operation areaAverage; // or: areaAverage, areaIntegrate, min, max
regionType patch;
name wall;
fields (p U);
}
}
Operations:
| Operation | Description | Application |
| ----------- | ------------- | ------------- |
| volAverage | Volume-weighted average | Domain-averaged temperature |
| volIntegrate | Volume integral | Total mass in domain |
| areaAverage | Area-weighted average | Wall-averaged pressure |
| areaIntegrate | Area integral | Total force on wall |
| min | Field minimum | Detect negative alpha |
| max | Field maximum | Detect unphysical values |
| sum | Sum over cells/face | Total mass flow rate |
Sampling and Probes :: Line, Plane, and Point Measurements
Point probes and line/plane sampling are the primary tools for time-series analysis and spatial profile extraction:
// Point probe
probe1
{
type probes;
libs ("libfieldFunctionObjects.so");
fields (p U);
probeLocations
(
(0.5 0.1 0.0) // point 1 coordinates
(1.0 0.1 0.0) // point 2 coordinates
);
writeControl timeStep;
writeInterval 1;
}
Line sampling:
line1
{
type sample;
libs ("libsampling.so");
application sample;
interpolationScheme linear;
log true;
fields (p U); // fields to sample
// Single line from point A to point B in n cells
sets
(
wakeLine
{
type line;
points ((0.0 0.0 0.0) (5.0 0.0 0.0));
nPoints 50; // number of sample points
}
// Plane sampling
wakePlane
{
type facePlane;
points ((0.0 -1.0 0.0) (0.0 1.0 0.0)); // two points defining plane normal
nCells 20;
}
);
}
Wave probes (for free-surface VOF simulations):
waveProbe1
{
type waveProbe;
libs ("libfieldFunctionObjects.so");
sampleAlpha true; // sample volume fraction (free surface)
probeLocations
(
(0.5 0.0 0.0)
(1.0 0.0 0.0)
);
}
The waveProbe functionObject is specific to multiphase (VOF) simulations and tracks the time history of the free surface elevation — useful for wave energy, breaking wave, and ship-resistance simulations.
forces and forceCoeffs :: Drag, Lift, and Moment Computation
The force and forceCoeffs functionObjects are the most commonly-used post-processing tools in external aerodynamics. They compute the total force on a specified patch by integrating pressure and viscous stress:
forceCoeffs
{
type forceCoeffs;
libs ("libforces.so");
patchNames (wing);
liftDir (0 1 0); // unit vector for lift direction
dragDir (1 0 0); // unit vector for drag direction (flow direction)
rhoName none; // or: rhoInf (incompressible), rho (compressible)
rhoInf 1.225; // density (for incompressible)
pName p; // pressure field
UName U; // velocity field
tauName tauw; // shear stress field (optional)
CofR (0 0 0); // center of rotation for moment computation
pitchAxis (0 0 1); // axis for pitch moment
rollAxis (1 0 0); // axis for roll moment
yawAxis (0 0 1); // axis for yaw moment
referenceArea 0.5; // reference area (m²)
}
The force vector components are computed as:
=F_i = \int_{S} (-p n_i + \tau_{ij} n_j) dS = \int_{S} \sigma_{ij} n_j dS
where =\sigma_{ij}/ is the stress tensor and =S/ is the specified patch. The drag direction and lift direction define the projection axes:
=F_D = \vec{F} \cdot \hat{d}_{drag}/, =C_D = F_D / (0.5 \rho U^2 A)/
The moment computation about the center of rotation (CofR):
=\vec{M} = \int_{S} \vec{r} \times (-p \hat{n} + \vec{\tau} \cdot \hat{n}) dS
where =\vec{r} = \vec{x} - \vec{x}_{CofR}/.
For aerodynamic performance, the standard coefficients are:
| Coefficient | Definition | Typical Range |
| ------------- | ------------ | --------------- |
| C_D (drag) | F_D / (0.5 \rho U² A) | 0.01 (airfoil) to 1.3 (blunt body) |
| C_L (lift) | F_L / (0.5 \rho U² A) | -0.5 to 2.0 (typical airfoil) |
| C_M (pitch) | M / (0.5 \rho U² A c) | -0.1 to 0.1 (airfoil) |
| C_T (thrust) | F_T / (0.5 \rho U² A) | Variable (propellers) |
postProcess utility :: Post-Simulation Analysis
The postProcess utility runs functionObjects that are not specified in controlDict. This is useful for post-hoc analysis of already-computed data:
[#BEGIN_SRC bash # Sample a plane from existing data postProcess -func "sample {(wakePlane { type facePlane; points ((0 -1 0) (0 1 0)); nCells 20; })}"
postProcess -func "forceCoeffs { patchNames (wing); rhoInf 1.225; referenceArea 0.5; }"
postProcess -func "fieldValues { type volFieldValue; operation volAverage; fields (p U); regionType patch; name myPatch; }"
#+END_SRC
The postProcess utility reads field data from the specified time directory and evaluates the functionObjects. It is non-destructive: no field data is modified, only analysis output is written to postProcessing/.
foamToVTK and ParaView :: VTK Export
foamToVTK converts OpenFOAM field data to VTK (Visualization Toolkit) format for use in ParaView:
[#BEGIN_SRC bash foamToVTK -time 0:100 # convert all timesteps 0 to 100 foamToVTK -time 50 # convert only timestep 50 foamToVTK -latestTime # convert only the latest time foamToVTK -legacy # legacy VTK format (older ParaView) foamToVTK -vtk # XML VTK format (newer ParaView)
#+END_SRC
The VTK output is written to the system/VTK/ directory, with subdirectories for each timestep. The VTK format supports both cell-centered and node-centered data (OpenFOAM is cell-centered; ParaView interpolates to nodes for visualisation).
paraFoam is the convenience wrapper that launches ParaView with the OpenFOAM reader:
[#BEGIN_SRC bash paraFoam -builtin # launch ParaView with built-in OpenFOAM reader paraFoam # launch system ParaView with .OpenFOAM reader
#+END_SRC
The -builtin flag uses ParaView's internal OpenFOAM reader (faster, more up-to-date). The system reader (without -builtin) uses the .OpenFOAM reader installed with ParaView.
For ParaView integration, see openfoam_paraview-architecture, openfoam_paraview-postprocessing, and openfoam_paraview-probes-sampling (when written).
For now: OpenFOAM's native VTK export is the primary interface to ParaView. ParaView is the standard post-processing tool across ALL CFD platforms — Fluent, Star-CCM+, and OpenFOAM all export to VTK for cross-platform consistency. See openfoam_paraview-architecture for details (when written).
Python automation :: paraview.simple and pvpython
OpenFOAM supports Python scripting for post-processing through the paraview.simple module (ParaView's Python interface) and pvpython (ParaView's Python executable):
# paraview.simple example - extract and visualise data from OpenFOAM case
from paraview.simple import *
# Load OpenFOAM case
case = OpenFOAMReader('myCase', RemoteClient=remote)
# Show data
data = Show(case)
# Apply filters
cont = Contour(Input=data)
cont.Isosurfaces = [3.14]
stream = Streamline(Input=data)
stream.Vector = ['U']
# Save screenshot
SaveScreenshot('myScreenshot.png', data)
# Save animation
AnimationScene = GetAnimationScene()
for i in range(AnimationScene.TimestepValues):
AnimationScene.CurrentTimeStep = i
SaveScreenshot(f'screenshot_{i:04d}.png', data)
For custom analysis (not just visualisation), write Python scripts that read OpenFOAM field data directly:
import numpy as np
from FoamFile import FoamFile # third-party: foamfile or pythonFoam
# Read OpenFOAM field
p = FoamFile('0/p')
U = FoamFile('0/U')
# Compute pressure coefficient
rho = 1.225 # density (kg/m³)
U_inf = 30 # free-stream velocity (m/s)
q_inf = 0.5 * rho * U_inf * U_inf # dynamic pressure
# C_P = (p - p_inf) / q_inf
p_inf = p.internalField[0] # reference pressure
C_p = (p.internalField - p_inf) / q_inf
# Integrate over face values for force
# ... (analysis code)
The pythonFoam package (third-party) provides a Python interface to OpenFOAM field data. It reads OpenFOAM dictionary fields directly without needing ParaView or VTK export.
See Also :: Related Notes
. Turbulence Models — Q-criterion, turbulence visualisation . OpenFOAM Solver Selection — which solvers provide which fields . OpenFOAM Case Setup — controlDict and functionObjects configuration . OpenFOAM Multiphase Flows — waveProbes for VOF simulations . OpenFOAM Parallel Computing — parallel I/O and reconstruction . ANSYS Meshing & Post-Processing — Fluent's post-processing comparison . ANSYS vs OpenFOAM Comparison — post-processing comparison
References
. OpenFOAM User Guide. ESI OpenCFD. (functionObjects reference.) . OpenFOAM Programming Guide. ESI OpenCFD. (functionObject development.) . paraView documentation. Kitware Inc. (VTK reader and Python interface.) . ANSYS Fluent Theory Guide. ANSYS Inc. (post-processing tools.)