pimpleFoam is OpenFOAM's general-purpose transient incompressible solver. It uses the PIMPLE algorithm — a merge of PISO and SIMPLE — that gives you control over the trade-off between speed and accuracy per time step through the nOuterCorrectors setting. Getting these settings wrong leads to divergence, slow convergence, or unnecessarily expensive simulations. This guide explains every PIMPLE setting with practical examples.
These three pressure-velocity coupling algorithms differ in how many times they iterate within each time step:
nOuterCorrectors = 1 it is identical to PISO. With nOuterCorrectors = 20 it can handle Co >> 1, because the outer loop provides the iteration needed for accuracy.pimpleFoam always runs the PIMPLE algorithm. The behaviour is controlled entirely by nOuterCorrectors.
pimpleFoam is the right solver for: unsteady RANS or LES simulations, vortex shedding, rotating machinery with sliding mesh (MRF or AMI), and any transient incompressible flow where temporal accuracy matters. For steady-state problems, use simpleFoam. For compressible flows, use rhoPimpleFoam.
// system/fvSolution — PIMPLE block
PIMPLE
{
nOuterCorrectors 2; // outer SIMPLE-like iterations per timestep
nCorrectors 1; // pressure corrections per outer corrector
nNonOrthogonalCorrectors 0; // extra pressure solves for non-orth meshes
pRefCell 0;
pRefValue 0;
}
With a single outer corrector, pimpleFoam is equivalent to PISO. This is the most efficient option if your Courant number is below 1. Use it for DNS-like LES, acoustic simulations, or any case where you want maximum temporal accuracy with small time steps.
PIMPLE
{
nOuterCorrectors 1;
nCorrectors 2; // increase to 3 for non-orth meshes
nNonOrthogonalCorrectors 0;
}
Ensure Co < 1 (ideally < 0.5 for accuracy) when using this setting.
The most common production setting. Allows Co up to about 5–10 while still producing accurate results. Each outer iteration solves momentum and pressure once, refining the non-linearity. This is the right default for most engineering transient simulations.
PIMPLE
{
nOuterCorrectors 3;
nCorrectors 1;
nNonOrthogonalCorrectors 1;
}
When you want to use a very large time step (Co up to 50–100) for faster wall-clock time at the expense of temporal accuracy, increase outer correctors to 10–50 and add residualControl to stop early when converged. This is used for pseudo-transient initialisation or slowly-varying flows.
PIMPLE
{
nOuterCorrectors 50;
nCorrectors 1;
nNonOrthogonalCorrectors 0;
residualControl
{
U 1e-4;
p 1e-3;
}
}
With residualControl, the outer loop exits as soon as all monitored residuals drop below the specified tolerance — so most time steps will use far fewer than 50 outer iterations in practice.
nCorrectors controls how many times the pressure equation is solved within each outer corrector. Increasing it improves the pressure-velocity coupling but adds cost. The default of 1 is sufficient for most cases. Increase to 2 or 3 if you see poor pressure convergence or oscillating velocity fields, especially on non-orthogonal meshes.
For meshes with significant non-orthogonality (max non-orthogonality > 50° in checkMesh), extra pressure solves are needed to correct the non-orthogonal flux error. Set nNonOrthogonalCorrectors to 1 for moderately non-orthogonal meshes (<70°) and to 2–3 for highly non-orthogonal meshes.
// checkMesh output showing when to add nNonOrthogonalCorrectors:
// Mesh non-orthogonality Max: 68.5 average: 12.3 → set to 1
// Mesh non-orthogonality Max: 78.2 average: 22.1 → set to 2
In pimpleFoam, system/controlDict controls the time step. Use adjustable time stepping for most cases — it reduces deltaT automatically when the flow is fast and increases it during quieter periods:
// system/controlDict
application pimpleFoam;
startFrom latestTime;
stopAt endTime;
endTime 10;
deltaT 0.001; // initial deltaT; will be adjusted
writeControl adjustableRunTime;
writeInterval 0.1;
adjustTimeStep yes;
maxCo 5; // with nOuterCorrectors=3, Co=5 is acceptable
maxDeltaT 0.01; // cap to prevent deltaT growing too large
The maxCo target should be matched to your nOuterCorrectors choice: Co ≤ 1 for nOuterCorrectors = 1, Co ≤ 5 for nOuterCorrectors = 2–3, Co ≤ 50 for nOuterCorrectors = 10–50.
Unlike simpleFoam, pimpleFoam does not need under-relaxation to be stable when nOuterCorrectors = 1. However, when using many outer correctors (large deltaT mode), adding relaxation factors helps convergence within each time step:
// system/fvSolution — relaxation for large-deltaT PIMPLE
relaxationFactors
{
equations
{
U 0.9; // milder than SIMPLE (0.7)
k 0.7;
omega 0.7;
}
}
// For the final outer corrector, use full relaxation (factor = 1)
// by adding "Final" entries:
relaxationFactors
{
equations
{
UFinal 1;
kFinal 1;
omegaFinal 1;
}
}
By default, turbulence quantities (k, omega/epsilon, nut) are solved once per time step, outside the PIMPLE outer corrector loop. To include turbulence in each outer corrector (more accurate but slower), add:
PIMPLE
{
nOuterCorrectors 3;
nCorrectors 1;
nNonOrthogonalCorrectors 0;
turbOnFinalIterOnly true; // default: only solve turbulence on final iter
// set to false to solve turbulence every outer corrector (more accurate)
}
Setting turbOnFinalIterOnly false is recommended for cases with strong turbulence-flow coupling (high-Re separated flows, rapidly changing boundary conditions).
The discretisation schemes in system/fvSchemes significantly affect stability and accuracy. For pimpleFoam, temporal accuracy requires a second-order time scheme. The recommended setup:
// system/fvSchemes — recommended for pimpleFoam
ddtSchemes
{
default Euler; // first order, robust for startup
// use backward for second-order temporal accuracy:
// default backward;
}
gradSchemes
{
default Gauss linear;
grad(U) cellLimited Gauss linear 1;
}
divSchemes
{
default none;
div(phi,U) Gauss linearUpwind grad(U); // bounded, good accuracy
div(phi,k) Gauss limitedLinear 1;
div(phi,omega) Gauss limitedLinear 1;
div((nuEff*dev2(T(grad(U))))) Gauss linear;
}
laplacianSchemes
{
default Gauss linear corrected; // corrected for non-orth meshes
}
Use Euler (first-order) for the first few time steps during startup to avoid divergence from sharp initial conditions, then switch to backward (second-order) for the production run. The switch can be done by changing fvSchemes mid-run; OpenFOAM reads fvSchemes at every write time step.
When using nOuterCorrectors > 1, pimpleFoam prints residuals for each outer corrector. Monitor these to verify the outer loop is actually converging within each time step. If residuals are not decreasing between outer correctors, the time step is too large or the linear solvers are not converging internally.
// Example pimpleFoam log output — outer corrector residuals
// Time = 0.1
// PIMPLE: Iteration 1
// Solving for Ux, Initial residual = 0.023, Final residual = 0.0012
// Solving for p, Initial residual = 0.041, Final residual = 0.0008
// PIMPLE: Iteration 2
// Solving for Ux, Initial residual = 0.0015, Final residual = 0.00007
// Solving for p, Initial residual = 0.0009, Final residual = 0.00004
// ExecutionTime = 0.85 s
A drop of one order of magnitude per outer corrector is normal. If residuals are not dropping at all between outer correctors, increase nCorrectors first, then check whether the mesh quality or time step is the limiting factor.
// system/fvSolution — typical pimpleFoam setup
solvers
{
p
{
solver GAMG;
smoother GaussSeidel;
tolerance 1e-7;
relTol 0.01;
}
pFinal
{
$p;
relTol 0;
}
"(U|k|omega|epsilon)"
{
solver smoothSolver;
smoother symGaussSeidel;
tolerance 1e-8;
relTol 0.1;
}
"(U|k|omega|epsilon)Final"
{
$U;
relTol 0;
}
}
PIMPLE
{
nOuterCorrectors 2;
nCorrectors 1;
nNonOrthogonalCorrectors 1;
turbOnFinalIterOnly true;
pRefCell 0;
pRefValue 0;
}
Upload your case and CFDpilot recommends nOuterCorrectors, nCorrectors, and nNonOrthogonalCorrectors based on your flow and mesh.
Optimise my PIMPLE →pisoFoam uses the PISO algorithm with exactly 2-3 pressure corrections per time step and no outer iterations — it requires Co < 1. pimpleFoam uses the PIMPLE algorithm which adds outer corrector loops around PISO. With nOuterCorrectors=1, pimpleFoam is identical to pisoFoam. pisoFoam is deprecated in recent OpenFOAM versions in favour of pimpleFoam.
Use nOuterCorrectors=1 with Co < 1 for LES or DNS-accuracy simulations. Use nOuterCorrectors=2-3 with maxCo=5 for standard engineering transient simulations. Use nOuterCorrectors=10-50 with residualControl for large time step pseudo-transient runs. More than 50 outer correctors is rarely beneficial.
nNonOrthogonalCorrectors adds extra pressure solves to account for the non-orthogonal correction in the pressure Laplacian. Set it to 0 for orthogonal meshes (non-orthogonality < 50°), 1 for moderately non-orthogonal meshes (50–70°), and 2–3 for highly non-orthogonal meshes (>70°).
No relaxation factors are needed with nOuterCorrectors=1 (PISO mode). With nOuterCorrectors > 1, adding equation relaxation (U: 0.9, k: 0.7, omega: 0.7) helps convergence within each time step. Always set the corresponding Final entries (UFinal, kFinal, etc.) to 1.0 to ensure the last outer corrector uses full relaxation.
residualControl in the PIMPLE block causes the outer corrector loop to exit early when all monitored field residuals drop below the specified tolerances. Setting U: 1e-4 and p: 1e-3 means the loop stops as soon as both conditions are met, even if nOuterCorrectors is set to 50. This makes large nOuterCorrectors computationally efficient for most time steps.
With nOuterCorrectors=1, keep Co < 1. With nOuterCorrectors=2-3, Co up to 5–10 is acceptable. With nOuterCorrectors=10-50 and residualControl, Co up to 50–100 can be used for pseudo-transient runs, but temporal accuracy is sacrificed. Always verify results are independent of time step size by testing with a smaller deltaT.