1.1. OpenFOAM Language¶
This is the OpenFOAM language.
1.1.1. What are features of C++?¶
Feature |
Meaning |
---|---|
typedefs |
Alias for a possibly complex type name |
function |
Group of statements that perform a task |
pointers |
Data type that holds addresses to refer to values in memory (e.g. for dynamic memory allocation) |
data structures |
Data members grouped under one name (e.g. the nodes in a linked list) |
classes |
Data members and function members grouped under one name |
constructor |
Function member that initialises the instance of it’s class |
destructor |
Function member that destroys the instance of it’s class |
friends |
Allows a function or class access to private or protected members of a class |
inheritance |
Allows a class to be created based on another class (so code can be reused) |
virtual member functions |
Member function that will be redefined in a derived class |
abstract class |
Class that contains at least one virtual function |
template |
Family of classes (class template), functions (function template), variables (variable template) or alias of a family of types (alias template) |
namespace |
Prevents name conflicts in large projects |
1.1.2. What is explicit evaluation?¶
Evaluate spatial derivatives at the current timestep
Uses known values
1.1.3. What is implicit evaluation?¶
Evaluate spatial derivatives at future timestep
Uses unknown values - generates a matrix equation to be solved
1.1.4. What are the higher level data types?¶
Type |
Meaning |
---|---|
volScalarField
|
scalar, e.g. pressure |
volVectorField
|
vector, e.g. velocity |
volTensorField
|
tensor, e.g. Reynolds Stress |
surfaceScalarField
|
surface scalar, e.g. flux |
dimensionedScalar
|
constant, e.g. viscosity |
1.1.5. What are fields?¶
Arrays of data stored at cell centres in the mesh
Include bouundary information
- Three types
volScalarField
volVectorField
volTensorField
Values are stored in named dictionary files in named timestep directories e.g.
case/0/p
for pressure
1.1.7. What are the five basic classes?¶
Class |
Meaning |
---|---|
fvPatchField
(and derived classes) |
Boundary conditions |
lduMatrix
fvMatrix
(and linear solvers) |
Sparse matrices |
1.1.8. What are the three space-time classes?¶
Class |
Meaning |
---|---|
polyMesh
|
|
fvMesh
|
|
Time
|
|
1.1.9. What are the three field algebra classes?¶
Class |
Meaning |
---|---|
Field<Type>
|
|
dimensionedField
|
|
geometricField<Type>
|
|
1.1.10. What are the two discretisation classes?¶
Class |
Meaning |
---|---|
fvc
|
|
fvm
|
|
1.1.11. What is a geometricField<Type>?¶
volField<Type>
surfaceField<Type>
pointField<Type>
1.1.12. What is the objectRegistry?¶
Object registry of entities (dictionaries, fields) which are to be read in or written out
1.1.13. What is the IOobject?¶
Defines I/O attributes of entities managed by the object registry.
1.1.14. How is a dictionary object read?¶
Code |
Meaning |
---|---|
Info << "Reading transportProperties" << endl;
|
Send message to screen |
IOdictionary transportProperties
(
IOobject
(
"transportProperties",
runTime.constant(),
mesh,
IOobject::MUST_READ
IOobject::NO_WRITE
)
);
|
Read in at creation |
dimensionedScalar nu
(
transportProperties.lookup("nu")
);
|
Lookup viscosity in dictionary |
1.1.15. How is volVectorField read from disk?¶
Code |
Meaning |
---|---|
volVectorField U
(
IOobject
(
"U",
Times[i].name(),
runTime,
IOobject::MUST_READ
),
mesh
)
|
|
1.1.16. How is volScalarField constructed?¶
Code |
Meaning |
---|---|
volVectorField magU
(
IOobject
(
"magU",
Times[i].name(),
runTime,
IOobject::NO_READ
IOobject::AUTO_WRITE
),
::mag(U)
);
magU.write();
|
|
1.1.17. What are the read and write options?¶
Class |
Meaning |
---|---|
NO_READ
|
Object created |
MUST_READ
READ_IF_PRESENT
|
Object asked to read |
NO_WRITE
|
Object destroyed |
AUTO_WRITE
|
Object asked to write |
1.1.18. How are objects represented in OpenFOAM?¶
How to create an object that writes the magnitude of a velocity vector?
Class |
Meaning |
---|---|
#include "fvCFD.H"
int main(int argc, char argv[])
{
# include "addTimeOptions.H"
# include "setRootCase.H"
# include "createTime.H"
instantList Times = runTime.times();
# include "createMesh.H"
|
|
for(label i=0; i<runTime.size(); i++)
{
runTime.setTime(Times[i],i);
Info << "Time: " << runTime.value() << endl
volVectorField U
(
IOobject
(
"U",
Times[i].name(),
runTime,
IOobject::MUST READ
),
mesh
);
|
|
volScalarField magU
(
IOobject
(
"magU",
Times[i].name(),
runTime,
IOobject::NO READ,
IOobject::AUTO WRITE
),
::mag(U)
);
magU.write();
} return 0;}
|
|
1.1.19. How is matrix inversion done in fvm?¶
Each operator in fvm constructs particular entries in known
M
andy
as afvMatrix
objectfvMatrix
is a template class (actual classes arefvScalarMatrix
etc)fvMatrix
handles storage vialduMatrix
classfvMatrix
class also handles solution
1.1.20. What are lists?¶
Class |
Meaning |
---|---|
List<Type>
|
|
PtrList<Type>
|
List of pointers |
SLList<Type>
|
Non-intrusive singly-linked list |
1.1.21. What are fields?¶
Class |
Meaning |
---|---|
Field<Type>
|
|
1.1.22. How is memory accessed?¶
Arrays
Pointers
References
1.1.23. How is IO Communication done?¶
Code |
Meaning |
---|---|
Info << "Time = " << runTime.timeName() << nl << endl;
|
Info object is output to the screen |
1.1.24. How are derivatives of fields evaluated?¶
Time derivative
- Divergence (div)
Spatial derivative
Discretised using the flux at the faces
e.g. \(\nabla \cdot (\mathbf{u}q)\) (the advection term)
- Gradient (grad)
Spatial derivative
e.g. \(\nabla p\) in the momentum equation
- Laplacian
Spatial derivative
- Discretised as \(\nabla \cdot \mu \nabla q\)
gradient scheme for \(\nabla q\)
interpolation for \(\mu\)
discretisation for \(\nabla \cdot\)
e.g. \(\mu \nabla^2 q\) in the momentum equation
1.1.25. What are the functions for discretisation?¶
Function |
Meaning |
---|---|
fvc::ddt(A)
fvm::ddt(A)
|
|
fvc::ddt(rho,A)
fvm::ddt(rho,A)
|
|
fvc::d2dt2(rho,A)
fvm::d2dt2(rho,A)
|
|
fvc::grad(A)
fvm::grad(A)
|
|
fvc::div(A)
fvm::div(A)
|
|
fvc::laplacian(A)
fvm::laplacian(A)
|
|
fvc::laplacian(mu, A)
fvm::laplacian(mu, A)
|
|
fvc::curl(A)
fvm::curl(A)
|
|
fvm::div(phi,A)
|
|
fvm::Sp(rho,A)
|
|
fvm::SuSp(rho,A)
|
|
1.1.26. How can are equations translated into code?¶
Equation |
Code |
---|---|
\({{\partial q} \over {\partial t}} + \nabla \cdot q \mathbf{u} = \mu \nabla^2 q\) |
fvScalarMatrix transport
(
fvm::ddt(q)
+ fvm::div(phi,q)
- fvm::laplacian(mu,q)
);
// phi is the flux from the momentum equation
|
\({{\partial T} \over {\partial t}} = \kappa \nabla^2 T\) |
solve(fvm::ddt(T) == kappa*fvc::laplacian(T))
// T is a volScalarField defined on the mesh
// A discretised representation of the field variable T
// solve performs matrix inversion for one step
|
\({{\partial k} \over {\partial t}} + \nabla \cdot k \mathbf{u} - \nabla \cdot [(\nu + \nu_t)\nabla k ]=\nu_t[1/2(\nabla \mathbf{u} + \nabla \mathbf{u}^T ]^2 - \varepsilon/k\) |
solve(
fvm::ddt(k)
+ fvm::div(phi,k)
- fvm::laplacian(nu()+nut,k)
== nut*magSqr(symm(fvc::grad(U)))
- fvm::Sp(epsilon/k,k)
);
|
1.1.27. How is the PISO algorithm programmed?¶
The PISO (Pressure Implicit with Splitting of Operators) is an efficient method to solve the Navier-Stokes equations
The algorithm can be summed up as follows:
Set the boundary conditions.
Solve the discretized momentum equation to compute an intermediate velocity field.
Compute the mass fluxes at the cells faces.
Solve the pressure equation.
Correct the mass fluxes at the cell faces.
Correct the velocities on the basis of the new pressure field.
Update the boundary conditions.
Repeat from 3 for the prescribed number of times.
Increase the time step and repeat from 1.
The implementation:
Define the equation for U
fvVectorMatrix UEqn
(
fvm::ddt(U)
+ fvm::div(phi, U)
- fvm::laplacian(nu, U)
);
Solve the momentum predictor
solve (UEqn == -fvc::grad(p));
Calculate the ap coefficient and calculate U
volScalarField rUA = 1.0/UEqn().A();
U = rUA*UEqn().H();
Calculate the flux
phi = (fvc::interpolate(U) & mesh.Sf())
+ fvc::ddtPhiCorr(rUA, U, phi);
adjustPhi(phi, U, p);
Define and solve the pressure equation and repeat for the prescribed number of non-orthogonal corrector steps
fvScalarMatrix pEqn
(
fvm::laplacian(rUA, p) == fvc::div(phi)
);
pEqn.setReference(pRefCell, pRefValue);
pEqn.solve();
Correct the flux
if (nonOrth == nNonOrthCorr)
{
phi -= pEqn.flux();
}
Calculate continuity errors
# include "continuityErrs.H"
Perform the momentum corrector step
U -= rUA*fvc::grad(p);
U.correctBoundaryConditions();
The following is from the OpenFOAM UK Users Group:
1.1.28. What are header files?¶
Sections of code in separate files that are widely used - all function prototypes in a header file
Equation |
Code |
---|---|
#include "CourantNumber.H"
|
File containing code for calculating Courant number |
1.1.29. What is wmake?¶
wmake is a make system – directs the compiler to compile specific files in particular ways.
- Controlled through files in Make:
files – specifies which user-written files to compile and what to call the result
options – specifies additional header files/libraries to be included in the compilation.