17_field
Important
Visit https://aerosand.cc for the latest updates.
0. Preface
Recalling the previous discussions, we have covered input/output, command-line arguments, time, and meshes. Most computations in OpenFOAM are based on physical fields. This project begins the discussion of “fields” in OpenFOAM.
This section primarily discusses:
- Understanding the code structure of fields
- Understanding how fields participate in computations
- Compiling and running a field project
1. Project Preparation
Run the following commands in the terminal to create the project:
ofsp
foamNewApp ofsp_17_field
cd ofsp_17_field
cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity debug_case
code .Test the initial solver, and provide scripts and documentation.
2. Field Creation
2.1. dimensionSet
We previously encountered OpenFOAM’s predefined units, which are defined in $FOAM_SRC/OpenFOAM/dimensionSet/dimensionSets.C. This file also defines many predefined unit combinations.
Excerpts are shown again below:
| |
Again, we will not delve into the implementation details for now.
We can set custom physical units for variables, for example:
dimensionSet dimAerosand(1,2,3,4,5,6,7); // just for example
2.2. dimensionedType
Find the class definition:
API page: https://api.openfoam.com/2506/dimensionedType_8H.html
Run the following command in the terminal to find the source code:
find $FOAM_SRC -iname dimensionedType.HLocate and excerpt the constructors as follows:
| |
Correspondingly, similar constructions can be seen in OpenFOAM code, such as:
| |
In dimensionedType.H, associated member functions are also defined, for example:
| |
Correspondingly, we can conveniently use the value() member function, for example, to obtain the value of airPressure above and then compute the maximum:
maxP = max(airPressure.value());Of course, OpenFOAM also provides other constructors and member functions, allowing us to construct our own physical quantities with units in different scenarios. At the current stage, we do not need to delve deeper into the source code. It is sufficient to understand that this is indeed how it works and that we will use it in this way in the future.
Note that OpenFOAM checks whether the final units on both sides of a mathematical equation are the same; if they differ, it will force an error and terminate the program. This issue will be encountered and addressed in subsequent code.
2.3. volFields
We will notice typical statements in OpenFOAM, such as:
| |
So, what is volScalarField? How is a field constructed?
API page: https://api.openfoam.com/2512/volFieldsFwd_8H.html
Run the following command in the terminal to view the source file:
find $FOAM_SRC -iname volFieldsFwd.HTip
Some students may wonder, “How do I know which file to look at?” Referring to the discussion in Section 06_tensor, after installing the OFextension plugin, you can simply right-click on the volScalarField keyword and jump to it. Alternatively, you can search for the keyword on the API page and read the relevant page.
The volFieldsFwd.H file contains type definitions as follows:
...
typedef GeometricField<scalar, fvPatchField, volMesh> volScalarField;
typedef GeometricField<vector, fvPatchField, volMesh> volVectorField;
...It can be seen that volFields include the common volScalarField and volVectorField, which are volume field quantities. Both volScalarField and volVectorField are actually different specializations of the GeometricField template. Therefore, volFields is just a collective term for a group of template specializations, not an actual class.
2.4. surfaceFields
Similarly, surface field quantities surfaceFields include the common surfaceScalarField and surfaceVectorField.
API page: https://api.openfoam.com/2506/surfaceFieldsFwd_8H.html
Run the following command in the terminal to view the source file:
find $FOAM_SRC -iname surfaceFieldsFwd.HThe surfaceFieldsFwd.H file contains type definitions as follows:
...
typedef GeometricField<scalar, fvsPatchField, surfaceMesh> surfaceScalarField;
typedef GeometricField<vector, fvsPatchField, surfaceMesh> surfaceVectorField;
...Thus, surfaceFields are also different specializations of the GeometricField template.
Tip
Why is “volume” abbreviated to “vol” in volFields but “surface” is written in full in surfaceFields? Perhaps it is due to historical reasons in the code…
2.5. GeometricField
Based on the discussion above, we examine the GeometricField.H code.
API page: https://api.openfoam.com/2506/GeometricField_8H.html
Run the following command in the terminal to view the source file:
find $FOAM_SRC -iname GeometricField.HExcerpt the main structure and several common constructors as follows:
| |
The above constructors correspond to actual field constructions, with examples as follows:
| |
These three examples correspond to the most common field constructors. Other constructors and more in-depth code-level analysis will be introduced gradually in the future, so there is no need to worry. Readers may also try to read a few more on their own.
3. Time Advancement of Fields
Taking the pressure field as an example, combined with field creation, we discuss the time advancement computation of fields.
3.1. Single Time Step Computation
The main source code ofsp_17_field.C is as follows:
| |
Tip
Note that the overwriting of the field in the main source code does not distinguish between the initial time step and subsequent time steps. Moreover, the foamCleanTutorials command cannot restore the content of the field files in the initial time step folder. Therefore, to avoid overwriting the initial conditions, it is highly recommended to back up the initial conditions. Once the initial field is overwritten, it can be restored at any time.
3.1.1. Scripts
Modify the caserun script as follows:
| |
Modify the caseclean script as follows:
| |
The modified scripts are more generic. Unless otherwise specified, they can be directly copied and used in the future.
3.1.2. Compilation and Execution
Run the following commands in the terminal to compile and run the project:
wclean
wmake
./caseclean
./caserunThe terminal output is as follows:
Create time
Create mesh for time = 0
Max p = 1.995
Min p = 0
Average p = 0.9975
Sum p = 399
ExecutionTime = 0.01 s ClockTime = 0 s
EndCheck the debug_case/ folder; an additional folder 0.005/ appears, and the computed field is written to 0.005/p. The final output corresponds to the field value at the latest time step.
3.2. Multi-Time Step Computation
How to advance computations over multiple time steps?
Modify the main source code as follows:
| |
Tip
On writing ++runTime instead of runTime++:
- In principle, pre-increment
++ais more efficient than post-incrementa++- Pre-increment
++aincrements directly and returns itself, avoiding potential copying - Post-increment creates a temporary copy, increments, and returns the temporary copy
- Pre-increment
- For built-in types (int, float, pointers, etc.), modern compilers generally optimize away the difference
- For complex types (classes, iterators), pre-increment is more efficient
Compile and run the project.
The terminal output is as follows:
Create time
Create mesh for time = 0
Max p = 5.985
Min p = 0
Average p = 2.9925
Sum p = 1197
ExecutionTime = 0.01 s ClockTime = 0 s
EndObserve that three additional time step folders appear in the debug_case/ folder. The file structure of the test case is now as follows:
tree debug_case/
debug_case/
├── 0
│ ├── p
│ └── U
├── 0.005
│ └── p
├── 0.01
│ └── p
├── 0.015
│ └── p
├── 0.org
│ ├── p
│ └── U
├── constant
│ ├── polyMesh/...
│ └── transportProperties
├── log.run
└── system/...Checking the pressure field values at each time step shows that the final output from the terminal corresponds to the computed value at the latest time step.
3.3. Dictionary-Controlled Computation
Even for multi-time step computations, we directly modify the number of time steps in the main source code, requiring recompilation of the entire application each time. For large applications, recompilation can be quite cumbersome.
In practice, we hope to control the computation through external files after the application is compiled, i.e., using OpenFOAM’s dictionary file controlDict to control the computation.
Modify the main source code as follows:
| |
Compile and run the project.
The terminal output is as follows:
Create time
Create mesh for time = 0
Max p = 199.5
Min p = 0
Average p = 99.75
Sum p = 39900
ExecutionTime = 0 s ClockTime = 0 s
EndSeveral additional time step folders appear in the debug_case/ folder: 0.1, 0.2, 0.3, 0.4, 0.5. The time steps at which data are written are controlled by system/controlDict.
Partial parameters of the controlDict dictionary are as follows (writing occurs every 0.005 * 20 = 0.1):
| |
These parameters can be modified in the dictionary at any time for testing without recompiling the project.
4. Summary
This section introduced “fields” in OpenFOAM. Through the code and project exercises, readers can understand how fields participate in computational projects.
This section has completed the following discussions:
- Understanding the code structure of fields
- Understanding how fields participate in computations
- Compiling and running a field project
Support us
Tip
Hopefully, the sharing here can be helpful to you.
If you find this content helpful, your comments or donations would be greatly appreciated. Your support helps ensure the ongoing updates, corrections, refinements, and improvements to this and future series, ultimately benefiting new readers as well.
The information and message provided during donation will be displayed as an acknowledgment of your support.
Copyright @ 2026 Aerosand
- Course (text, images, etc.):CC BY-NC-SA 4.0
- Code derived from OpenFOAM:GPL v3
- Other code:MIT License
