# 2.2 Basic input/output file format

OpenFOAM needs to read a range of data structures such as strings, scalars, vectors, tensors, lists and fields. The input/output (I/O) format of files is designed to be extremely flexible to enable the user to modify the I/O in OpenFOAM applications as easily as possible. The I/O follows a simple set of rules that make the files extremely easy to understand, in contrast to many software packages whose file format may not only be difficult to understand intuitively but also not be published anywhere. The description of the OpenFOAM file format is described in the following sections.

### 2.2.1 General syntax rules

The format follows some of the general principles of C++ source code.

• Files have free form, with no particular meaning assigned to any column and no need to indicate continuation across lines.
• Lines have no particular meaning except to a // comment delimiter which makes OpenFOAM ignore any text that follows it until the end of line.
• A comment over multiple lines is done by enclosing the text between /* and */ delimiters.

### 2.2.2 Dictionaries

OpenFOAM uses dictionaries as the most common means of specifying data. A dictionary is an entity that contains a set of data entries that can be retrieved by the I/O by means of keywords. The keyword entries follow the general format

<keyword>  <dataEntry1>  <dataEntryN>;
Most entries are single data entries of the form:

<keyword>  <dataEntry>;
Most OpenFOAM data files are themselves dictionaries containing a set of keyword entries. Dictionaries provide the means for organising entries into logical categories and can be specified hierarchically so that any dictionary can itself contain one or more dictionary entries. The format for a dictionary is to specify the dictionary name followed the entries enclosed in curly braces {} as follows

<dictionaryName>
{
keyword entries
}

### 2.2.3 The data file header

All data files that are read and written by OpenFOAM begin with a dictionary named FoamFile containing a standard set of keyword entries, listed in Table 2.1.

 Keyword Description Entry version I/O format version 2.0 format Data format ascii / binary location Path to the file, in "…" (optional) class OpenFOAM class constructed from the data file concerned typically dictionary or a field, e.g.volVectorField object Filename e.g.controlDict

Table 2.1: Header keywords entries for data files.

The table provides brief descriptions of each entry, which is probably sufficient for most entries with the notable exception of class. The class entry is the name of the C++ class in the OpenFOAM library that will be constructed from the data in the file. Without knowledge of the underlying code which calls the file to be read, and knowledge of the OpenFOAM classes, the user will probably be unable to surmise the class entry correctly. However, most data files with simple keyword entries are read into an internal dictionary class and therefore the class entry is dictionary in those cases.

The following example shows the use of keywords to provide data for a case using the types of entry described so far. The extract, from an fvSolution dictionary file, contains 2 dictionaries, solvers and PISO. The solvers dictionary contains multiple data entries for solver and tolerances for each of the pressure and velocity equations, represented by the p and U keywords respectively; the PISO dictionary contains algorithm controls.

17
18solvers
19{
20    p
21    {
22        solver          PCG;
23        preconditioner  DIC;
24        tolerance       1e-06;
25        relTol          0.05;
26    }
27
28    pFinal
29    {

### 2.2.7 Dimensioned types

Physical properties are typically specified with their associated dimensions. These entries have the format that the following example of a dimensionedScalar demonstrates:

nu             [0 2 -1 0 0 0 0]  1;
The first nu is the keyword; the next entry is the dimensionSet and the final entry is the scalar value.

### 2.2.8 Fields

Much of the I/O data in OpenFOAM are tensor fields, e.g. velocity, pressure data, that are read from and written into the time directories. OpenFOAM writes field data using keyword entries as described in Table 2.3.

 Keyword Description Example dimensions Dimensions of field [1 1 -2 0 0 0 0] internalField Value of internal field uniform (1 0 0) boundaryField Boundary field see file listing in section 2.2.8

Table 2.3: Main keywords used in field dictionaries.

The data begins with an entry for its dimensions. Following that, is the internalField, described in one of the following ways.

Uniform field
a single value is assigned to all elements within the field, taking the form:

internalField uniform <entry>;

Nonuniform field
each field element is assigned a unique value from a list, taking the following form where the token identifier form of list is recommended:

internalField nonuniform <List>;

The boundaryField is a dictionary containing a set of entries whose names correspond to each of the names of the boundary patches listed in the boundary file in the polyMesh directory. Each patch entry is itself a dictionary containing a list of keyword entries. The compulsory entry, type, describes the patch field condition specified for the field. The remaining entries correspond to the type of patch field condition selected and can typically include field data specifying initial conditions on patch faces (see Section 5.1). An example set of field dictionary entries for velocity U are shown below:

17dimensions      [0 1 -1 0 0 0 0];
18
19internalField   uniform (0 0 0);
20
21boundaryField
22{
23    movingWall
24    {
25        type            fixedValue;
26        value           uniform (1 0 0);
27    }
28
29    fixedWalls
30    {
31        type            noSlip;
32    }
33
34    frontAndBack
35    {
36        type            empty;
37    }
38}
39
40// ************************************************************************* //

There is additional file syntax that offers great flexibility for the setting up of OpenFOAM case files, namely directives and macro substitutions. Directives are commands that can be contained within case files that begin with the hash (#) symbol. Macro substitutions begin with the dollar ($) symbol. At present there are 4 directive commands available in OpenFOAM: #include "<fileName>" (or #includeIfPresent "<fileName>" reads the file of name <fileName>; #inputMode has the following options: • #default : provide default value if entry is not already defined • #overwrite : silently overwrites existing entries • #warn : warn about duplicate entries • #error : error if any duplicate entries occur • #merge : merge sub-directories when possible (the default mode) #remove <keywordEntry> removes any included keyword entry; can take a word or regular expression; #codeStream followed by verbatim C++ code, compiles, loads and executes the code on-the-fly to generate the entry. ### 2.2.10 The #include and #inputMode directives For example, let us say a user wishes to set an initial value of pressure once to be used as the internal field and initial value at a boundary. We could create a file, e.g. named initialConditions, which contains the following entries: pressure 1e+05; #inputMode merge In order to use this pressure for both the internal and initial boundary fields, the user would simply include the following macro substitutions in the pressure field file p: #include "initialConditions" internalField uniform$pressure;
boundaryField
{
patch1
{
type fixedValue;
value \$internalField;
}
}

This is a fairly trivial example that simply demonstrates how this functionality works. However, the functionality can be used in many, more powerful ways particularly as a means of generalising case data to suit the user’s needs. For example, if a user has a set of cases that require the same RAS turbulence model settings, a single file can be created with those settings which is simply included in the turbulenceProperties file of each case. Macro substitutions can extend well beyond a single value so that, for example, sets of boundary conditions can be predefined and called by a single macro. The extent to which such functionality can be used is almost endless.

### 2.2.11 The #codeStream directive

The #codeStream directive takes C++ code which is compiled and executed to deliver the dictionary entry. The code and compilation instructions are specified through the following keywords.

• code: specifies the code, called with arguments OStream& os and const dictionary& dict which the user can use in the code, e.g. to lookup keyword entries from within the current case dictionary (file).
• codeInclude (optional): specifies additional C++ #include statements to include OpenFOAM files.
• codeOptions (optional): specifies any extra compilation flags to be added to EXE_INC in Make/options.
• codeLibs (optional): specifies any extra compilation flags to be added to LIB_LIBS in Make/options.

Code, like any string, can be written across multiple lines by enclosing it within hash-bracket delimiters, i.e. #{…#}. Anything in between these two delimiters becomes a string with all newlines, quotes, etc. preserved.

An example of #codeStream is given below. The code in the controlDict file looks up dictionary entries and does a simple calculation for the write interval:

startTime       0;
endTime         100;
...
writeInterval   #codeStream
{
code
#{