Boundary and initial conditions are foundational elements in computational fluid dynamics simulations, forming the critical specifications that drive system behavior. In OpenFOAM, these conditions are defined within field files located in the 0/ directory, where the internalField section initializes the field across the domain, and the boundaryField section assigns a boundary condition for each mesh patch. While a wide range of native boundary conditions are available for many applications, certain modeling situations require a more customized approach. One of the simplest methods for implementing user-defined boundary or initial conditions in OpenFOAM is through the codeStream utility. codeStream is part of the OpenFOAM distribution and is generally easier to use than high-level programming, which requires extensive knowledge of OpenFOAM and C++.
The proper specification of boundary conditions is essential because, in the absence of sources and sinks, system behavior is driven by these conditions. Ill-posed combinations can lead to physically incorrect predictions and, in many cases, solver failure. OpenFOAM offers a wide range of conditions grouped by their application, including constraints for geometrical constraints (e.g., for 2-D, axisymmetric), general conditions available to all patch types and fields, inlet conditions, outlet conditions, wall conditions, and coupled conditions (e.g., cyclic). These conditions are assigned in the boundaryField section of field files for each mesh patch. The format follows a structured dictionary where each condition is set in a dictionary given by the name of the underlying mesh patch, with the type keyword specifying the boundary condition type.
Understanding Boundary Condition Implementation
In OpenFOAM, boundary conditions are implemented as patch fields, which are specific instances of the fvPatchField template class. Each boundary condition type provides specialized behavior for calculating field values at mesh boundaries. The base boundary conditions form the foundation for more complex and specialized conditions. These include:
fixedValueFvPatchField: Specifies a fixed value at the boundary.fixedGradientFvPatchField: Specifies a fixed gradient normal to the boundary.mixedFvPatchField: Blends fixed value and fixed gradient conditions.zeroGradientFvPatchField: Sets zero gradient normal to the boundary.
More complex and specialized boundary conditions derive from these base types. Flow rate boundary conditions, for example, specify a mass or volumetric flow through a boundary patch, rather than directly setting the velocity. The boundary condition system interacts with the mesh system and fields to enforce the specified behaviors at the domain boundaries.
The boundary conditions are specified in field files, such as p (pressure) and U (velocity), within time directories. These files include three primary entries: dimensions for the dimensional units, internalField for the initial internal field values, and boundaryField where the boundary conditions are specified. The boundaryField requires an entry for each patch in the mesh, as defined in the boundary file.
For example, in a 2D incompressible fluid case, the boundary file might define patches such as outlet, up (symmetry), hole (wall), frontAndBack (empty), and inlet. Correspondingly, in the field file, the boundaryField dictionary would specify the condition for each patch. For instance, the inlet patch might use a zeroGradient condition, the outlet might use a fixedValue condition with a uniform value, the up patch might use a symmetry condition, the hole might use zeroGradient, and the frontAndBack might use an empty condition. The empty condition is a constraint patch type used for 2D simulations to indicate that the front and back faces have no influence on the flow.
Using CodeStream for Custom Conditions
When the available native boundary conditions are insufficient, codeStream provides a method to implement custom logic. codeStream allows users to embed C++ code directly into the OpenFOAM case dictionary to define boundary or initial conditions. This utility is particularly useful for implementing conditions that depend on local coordinates, time, or other fields in a way that is not directly supported by the standard condition types.
The syntax for using codeStream is based on the ESI version v2312 of OpenFOAM. It typically involves defining a function or a class that returns the required field values or gradients. This approach is more flexible than using pre-defined conditions but requires a solid understanding of C++ and the OpenFOAM data structures.
For users who find codeStream too complex, external libraries such as swak4foam offer an alternative, often described as a higher-level programming approach. However, codeStream is integrated into OpenFOAM and is generally considered the simplest way to implement user-defined conditions without requiring additional libraries.
Practical Tips and Tricks
Several practical tips can simplify the process of setting boundary conditions in OpenFOAM. One useful technique is to include constraint types automatically. At the top of the boundary list in any field file, one can add #includeEtc "casedicts/setConstraintTypes". This line instructs OpenFOAM to look through the polyMesh/boundary file and automatically apply the boundaries based on their type. This can be especially useful for creating boundary condition templates that reduce the effort to apply case-specific boundary details. The file defining which boundary types can be applied with this line is located at $FOAM_ETC/caseDicts/setConstrainTypes.
Another helpful feature is the use of reference variables. Reference variables allow values that need to be used repeatedly to be referenced from a single location. For example, in some tutorials, the internalField entry is also applied at the inlet patch. When the OpenFOAM solver reads this boundary condition, it replaces the inlet value with the internalField value. The $ preceding the variable name is the flag that informs OpenFOAM that it is looking at a reference variable. This promotes consistency and ease of modification, as changing the internalField value automatically updates all references to it.
Common Boundary Condition Combinations and Usage
The system behavior is critically dependent on the combination of boundary conditions applied. For instance, in an incompressible flow simulation, a common setup might involve an inlet with a specified velocity or flow rate, an outlet with a pressure condition (often zeroGradient for pressure in incompressible flows), and walls with no-slip conditions. Incorrect combinations, such as specifying a fixed pressure at both inlet and outlet, can lead to solver failure or unphysical results.
The boundaryField dictionary structure is hierarchical. Each patch entry is a sub-dictionary containing the type and other specific parameters. For example, a fixedValue condition requires a value entry, which can be a uniform value or a non-uniform expression. The mixed condition requires both value and gradient entries, along with a refValue and refGradient for the blending. The zeroGradient condition does not require additional parameters beyond the type.
When solving the general transport equation, boundary conditions are used to provide either the value at the boundary, the gradient at the boundary, or a combination thereof. The choice depends on the physical situation being modeled. For example, for a temperature field, a wall might have a fixed temperature (fixed value) or a specified heat flux (fixed gradient).
Considerations for Mesh Patches
It is important to note that for 1-sided boundaries (e.g., external boundaries), the normal vector points out of the domain. This convention affects how gradients are calculated and interpreted. Non-orthogonality effects are typically not included in the standard boundary condition calculations but may be handled by the solver during the solution process.
The mesh topology, defined in the boundary file, directly influences which boundary conditions can be applied. Patches can be of different types (wall, inlet, outlet, symmetry, empty, etc.), and the boundary condition type in the field file must be compatible with the patch type defined in the mesh. For instance, a patch defined as symmetry in the mesh should typically use a symmetry boundary condition in the field file.
Conclusion
Setting boundary and initial conditions in OpenFOAM is a critical step in defining a simulation. The standard boundaryField dictionary in the 0/ directory provides a flexible framework for applying a wide range of conditions. For standard applications, the native boundary conditions are often sufficient. When more customization is needed, utilities like codeStream offer a powerful way to implement user-defined logic directly within the case setup. Practical tips such as using #includeEtc for constraint types and reference variables can streamline the process and reduce errors. Understanding the hierarchy of boundary condition types and their proper application based on the mesh patch definitions is essential for achieving physically accurate and solver-stable simulations.
Sources
- Boundary and initial conditions with codeStream in OpenFOAM
- OpenFOAM Documentation: Boundary Conditions
- OpenFOAM Boundary Conditions Tips and Tricks
- CFD-Online Forum: How to change/set different boundary condition for particular cell region
- DeepWiki: OpenFOAM-12 Boundary Conditions
- CFD Direct: OpenFOAM User Guide v13 - Boundary Conditions