[version 12][version 11][version 10][version 9][version 8][version 7][version 6]
4.5 Numerical schemes
The fvSchemes dictionary in the system directory sets the numerical schemes for terms, such as derivatives in equations, that are calculated during a simulation. This section describes how to specify the schemes in the fvSchemes dictionary.
The terms that must typically be assigned a numerical scheme in fvSchemes range from derivatives, e.g. gradient , to interpolations of values from one set of points to another. The aim in OpenFOAM is to oﬀer an unrestricted choice to the user, starting with the choice of discretisation practice which is generally standard Gaussian ﬁnite volume integration. Gaussian integration is based on summing values on cell faces, which must be interpolated from cell centres. The user has a wide range of options for interpolation scheme, with certain schemes being speciﬁcally designed for particular derivative terms, especially the advection divergence terms.
The set of terms, for which numerical schemes must be speciﬁed, are subdivided within the fvSchemes dictionary into the categories below.
 timeScheme: ﬁrst and second time derivatives, e.g.
 gradSchemes: gradient
 divSchemes: divergence
 laplacianSchemes: Laplacian
 interpolationSchemes: cell to face interpolations of values.
 snGradSchemes: component of gradient normal to a cell face.
 wallDist: distance to wall calculation, where required.
Each keyword in represents the name of a subdictionary which contains terms of a particular type, e.g.gradSchemes contains all the gradient derivative terms such as grad(p) (which represents ). Further examples can be seen in the extract from an fvSchemes dictionary below:
17ddtSchemes
18{
19 default Euler;
20}
21
22gradSchemes
23{
24 default Gauss linear;
25}
26
27divSchemes
28{
29 default none;
30
31 div(phi,U) Gauss linearUpwind grad(U);
32 div(phi,k) Gauss upwind;
33 div(phi,epsilon) Gauss upwind;
34 div(phi,R) Gauss upwind;
35 div(R) Gauss linear;
36 div(phi,nuTilda) Gauss upwind;
37
38 div((nuEff*dev2(T(grad(U))))) Gauss linear;
39}
40
41laplacianSchemes
42{
43 default Gauss linear corrected;
44}
45
46interpolationSchemes
47{
48 default linear;
49}
50
51snGradSchemes
52{
53 default corrected;
54}
55
56
57// ************************************************************************* //
The example shows that the fvSchemes dictionary contains 6 …Schemes subdictionaries containing keyword entries for each term speciﬁed within including: a default entry; other entries whose names correspond to a word identiﬁer for the particular term speciﬁed, e.g.grad(p) for If a default scheme is speciﬁed in a particular …Schemes subdictionary, it is assigned to all of the terms to which the subdictionary refers, e.g. specifying a default in gradSchemes sets the scheme for all gradient terms in the application, e.g. , . When a default is speciﬁed, it is not necessary to specify each speciﬁc term itself in that subdictionary, i.e. the entries for grad(p), grad(U) in this example. However, if any of these terms are included, the speciﬁed scheme overrides the default scheme for that term.
Alternatively the user can specify that no default scheme by the none entry, as in the divSchemes in the example above. In this instance the user is obliged to specify all terms in that subdictionary individually. Setting default to none may appear superﬂuous since default can be overridden. However, specifying none forces the user to specify all terms individually which can be useful to remind the user which terms are actually present in the application.
OpenFOAM includes a vast number of discretisation schemes, from which only a few are typically recommended for realworld, engineering applications. The user can get help with scheme selection by interrogating the tutorial cases for example scheme settings. They should look at the schemes used in relevant cases, e.g. for running a largeeddy simulation (LES), look at schemes used in tutorials running LES. Additionally, foamSearch provides a useful tool to get a quick list of schemes used in all the tutorials. For example, to print all the default entries for ddtSchemes for cases in the $FOAM_TUTORIALS directory, the user can type:
foamSearch $FOAM_TUTORIALS fvSchemes ddtSchemes/default
default backward;
default CrankNicolson 0.9;
default Euler;
default localEuler;
default none;
default steadyState;
4.5.1 Time schemes
The ﬁrst time derivative () terms are speciﬁed in the ddtSchemes subdictionary. The discretisation schemes for each term can be selected from those listed below.
 steadyState: sets time derivatives to zero.
 Euler: transient, ﬁrst order implicit, bounded.
 backward: transient, second order implicit, potentially unbounded.
 CrankNicolson: transient, second order implicit, bounded;
requires an oﬀcentering coeﬃcient where:
 localEuler: pseudo transient for accelerating a solution to steadystate using localtime stepping; ﬁrst order implicit.
Solvers are generally conﬁgured to simulate either transient or steadystate. Changing the time scheme from one which is steadystate to transient, or visa versa, does not aﬀect the fundamental nature of the solver and so fails to achieve its purpose, yielding a nonsensical solution.
Any second time derivative () terms are speciﬁed in the d2dt2Schemes subdictionary. Only the Euler scheme is available for d2dt2Schemes.
4.5.2 Gradient schemes
The gradSchemes subdictionary contains gradient terms. The default discretisation scheme that is primarily used for gradient terms is:
default Gauss linear;
In some tutorials cases, particular involving poorer quality meshes, the discretisation of speciﬁc gradient terms is overridden to improve boundedness and stability. The terms that are overridden in those cases are the velocity gradient
grad(U) cellLimited Gauss linear 1;
grad(k) cellLimited Gauss linear 1;
grad(epsilon) cellLimited Gauss linear 1;
Other schemes that are rarely used are as follows.
 leastSquares: a secondorder, least squares distance calculation using all neighbour cells.
 Gauss cubic: thirdorder scheme that appears in the dnsFoam simulation on a regular mesh.
4.5.3 Divergence schemes
The divSchemes subdictionary contains divergence terms, i.e. terms of the form …, excluding Laplacian terms (of the form ). This includes both advection terms, e.g. , where velocity provides the advective ﬂux, and other terms, that are often diﬀusive in nature, e.g. .
The fact that terms that are fundamentally diﬀerent reside in one subdictionary means that the default scheme in generally set to none in divSchemes. The nonadvective terms then generally use the Gauss integration with linear interpolation, e.g.
div(U) Gauss linear;
The treatment of advective terms is one of the major challenges in CFD numerics and so the options are more extensive. The keyword identiﬁer for the advective terms are usually of the form div(phi,…), where phi generally denotes the (volumetric) ﬂux of velocity on the cell faces for constantdensity ﬂows and the mass ﬂux for compressible ﬂows, e.g. div(phi,U) for the advection of velocity, div(phi,e) for the advection of internal energy, div(phi,k) for turbulent kinetic energy, etc. For advection of velocity, the user can run the foamSearch script to extract the div(phi,U) keyword from all tutorials.
foamSearch $FOAM_TUTORIALS fvSchemes "divSchemes/div(phi,U)"
Ignoring ‘V’schemes (with keywords ending “V”), and rarelyused schemes such as Gauss cubic and vanLeerV, the interpolation schemes used in the tutorials are as follows.
 linear: second order, unbounded.
 linearUpwind: second order, upwindbiased, unbounded (but much less so than linear), that requires discretisation of the velocity gradient to be speciﬁed.
 LUST: blended 75% linear/ 25%linearUpwind scheme, that requires discretisation of the velocity gradient to be speciﬁed.
 limitedLinear: linear scheme that limits towards upwind in regions of rapidly changing gradient; requires a coeﬃcient, where 1 is strongest limiting, tending towards linear as the coeﬃcient tends to 0.
 upwind: ﬁrstorder bounded, generally too inaccurate to be recommended.
Example syntax for these schemes is as follows.
div(phi,U) Gauss linear;
div(phi,U) Gauss linearUpwind grad(U);
div(phi,U) Gauss LUST grad(U);
div(phi,U) Gauss LUST unlimitedGrad(U);
div(phi,U) Gauss limitedLinear 1;
div(phi,U) Gauss upwind;
‘V’schemes are specialised versions of schemes designed for vector ﬁelds. They diﬀer from conventional schemes by calculating a single limiter which is applied to all components of the vectors, rather than calculating separate limiters for each component of the vector. The ‘V’schemes’ single limiter is calculated based on the direction of most rapidly changing gradient, resulting in the strongest limiter being calculated which is most stable but arguably less accurate. Example syntax is as follows.
div(phi,U) Gauss limitedLinearV 1;
div(phi,U) Gauss linearUpwindV grad(U);
The bounded variants of schemes relate to the treatment of the material time derivative which can be expressed in terms of a spatial time derivative and convection, e.g. for ﬁeld in incompressible ﬂow

(4.1) 
div(phi,U) bounded Gauss limitedLinearV 1;
div(phi,U) bounded Gauss linearUpwindV grad(U);
The schemes used for advection of scalar ﬁelds are similar to those for advection of velocity, although in general there is greater emphasis placed on boundedness than accuracy when selecting the schemes. For example, a search for schemes for advection of internal energy (e) reveals the following.
foamSearch $FOAM_TUTORIALS fvSchemes "divSchemes/div(phi,e)"
div(phi,e) bounded Gauss upwind;
div(phi,e) Gauss limitedLinear 1;
div(phi,e) Gauss LUST grad(e);
div(phi,e) Gauss upwind;
div(phi,e) Gauss vanLeer;
There are specialised versions of the limited schemes for scalar ﬁelds that are commonly bounded between 0 and 1, e.g. the laminar ﬂame speed regress variable . A search for the discretisation used for advection in the laminar ﬂame transport equation yields:
div(phiSt,b) Gauss limitedLinear01 1;
The multivariateSelection mechanism also exists for grouping multiple equation terms together, and applying the same limiters on all terms, using the strongest limiter calculated for all terms. A good example of this is in a set of mass transport equations for ﬂuid species, where it is good practice to apply the same discretisation to all equations for consistency. The example below comes from the smallPoolFire3D tutorial in $FOAM_TUTORIALS/combustion/ﬁreFoam/les, in which the equation for enthalpy is included with the specie mass transport equations in the calculation of a single limiter.
div(phi,Yi_h) Gauss multivariateSelection
{
O2 limitedLinear01 1;
CH4 limitedLinear01 1;
N2 limitedLinear01 1;
H2O limitedLinear01 1;
CO2 limitedLinear01 1;
h limitedLinear 1 ;
}
4.5.4 Surface normal gradient schemes
It is worth explaining the snGradSchemes subdictionary that contains surface normal gradient terms, before discussion of laplacianSchemes, because they are required to evaluate a Laplacian term using Gaussian integration. A surface normal gradient is evaluated at a cell face; it is the component, normal to the face, of the gradient of values at the centres of the 2 cells that the face connects.
A search for the default scheme for snGradSchemes reveals the following entries.
default corrected;
default limited corrected 0.33;
default limited corrected 0.5;
default orthogonal;
default uncorrected;
The basis of the gradient calculation at a face is to subtract the value at the cell centre on one side of the face from the value in the centre on the other side and divide by the distance. The calculation is secondorder accurate for the gradient normal to the face if the vector connecting the cell centres is orthogonal to the face, i.e. they are at rightangles. This is the orthogonal scheme.
Orthogonality requires a regular mesh, typically aligned with the Cartesian coordinate system, which does not normally occur in meshes for real world, engineering geometries. Therefore, to maintain secondorder accuracy, an explicit nonorthogonal correction can be added to the orthogonal component, known as the corrected scheme. The correction increases in size as the nonorthogonality, the angle between the cellcell vector and face normal vector, increases.
As tends towards 90, e.g. beyond 70, the explicit correction can be so large to cause a solution to go unstable. The solution can be stabilised by applying the limited scheme to the correction which requires a coeﬃcient where

(4.2) 
The corrected scheme applies underrelaxation in which the implicit orthogonal calculation is increased by , with an equivalent boost within the nonorthogonal correction. The uncorrected scheme is equivalent to the corrected scheme, without the nonorthogonal correction, so includes is like orthogonal but with the underrelaxation.
Generally the uncorrected and orthogonal schemes are only recommended for meshes with very low nonorthogonality (e.g. maximum 5). The corrected scheme is generally recommended, but for maximum nonorthogonality above 70, limited may be required. At nonorthogonality above 80, convergence is generally hard to achieve.
4.5.5 Laplacian schemes
The laplacianSchemes subdictionary contains Laplacian terms. A typical Laplacian term is , the diﬀusion term in the momentum equations, which corresponds to the keyword laplacian(nu,U) in laplacianSchemes. The Gauss scheme is the only choice of discretisation and requires a selection of both an interpolation scheme for the diﬀusion coeﬃcient, i.e. in our example, and a surface normal gradient scheme, i.e. . To summarise, the entries required are:
Gauss <interpolationScheme> <snGradScheme>
foamSearch $FOAM_TUTORIALS fvSchemes laplacianSchemes.default
default Gauss linear corrected;
default Gauss linear limited corrected 0.33;
default Gauss linear limited corrected 0.5;
default Gauss linear orthogonal;
default Gauss linear uncorrected;
4.5.6 Interpolation schemes
The interpolationSchemes subdictionary contains terms that are interpolations of values typically from cell centres to face centres, primarily used in the interpolation of velocity to face centres for the calculation of ﬂux phi. There are numerous interpolation schemes in OpenFOAM, but a search for the default scheme in all the tutorial cases reveals that linear interpolation is used in almost every case, except for 23 unusual cases, e.g. DNS on a regular mesh, stress analysis, where cubic interpolation is used.