OpenFOAM · git:20260414.2b184d0 · 2026-04-14 · sha256 b1f96af55d868453

OpenFOAM git:20260414.2b184d0C

Immutable. This exact content never changes and is served at /api/v1/blob/b1f96af55d868453.

> **MANDATORY EXECUTION POLICY** — READ BEFORE PROCEEDING
>
> You MUST run the **actual model binary or package** described in this document.
> If the model fails to import, compile, or execute, you MUST:
> 1. Check `diagnostics/triplets.yaml` for a matching error pattern
> 2. Try the fix suggested in the triplet's `remedy` section
> 3. If still failing, report the error to the user with full details
>
> You MUST NOT substitute a simplified Python formula, regression equation,
> or hand-coded approximation in place of the real model.
>
>
> Before starting, run: `python preflight_check.py` (in this KI directory)
> to verify that the model binary/package and required data are available.
>
> **DEBUGGING PROTOCOL** — When something goes wrong, follow this order:
> 1. **Check triplets** — `diagnostics/triplets.yaml` may already cover this error
> 2. **Read official docs** — The model's own documentation for expected formats/units
> 3. **Find working examples** — Check `outputs/` or the model's shipped test data
> 4. **Fix the tool** — With knowledge of what "correct" looks like
>
> Do NOT write custom debug scripts. The answers are in the docs and examples.

# OpenFOAM Knowledge Infrastructure

| Field | Value |
|-------|-------|
| Package | OpenFOAM-dev (CFD Framework) |
| Domain | Computational Fluid Dynamics / Hydraulics |
| Language | C++ (9,257 source files) |
| Build System | wmake (custom), Allwmake master script |
| License | GPL v3 |
| Source | https://github.com/OpenFOAM/OpenFOAM-dev |
| Tools | 7 |
| Diagnostic Triplets | 20 |
| Validation | cavity tutorial (lid-driven cavity benchmark) |

---

## Data Preparation

### Forcing data

**Data Sources**: Use `from ki_tools_common.load_forcing import load_daily_forcing` for CMFD/MSWX/NASA POWER.

**Data Validation Reference**: See `data_ki/CMFD/SKILL.md` for atmospheric forcing documentation.
See `data_ki/NOAA_Tides/SKILL.md` for tidal observation data.
See `data_ki/NDBC/SKILL.md` for wave buoy observations.


## 1. Overview

OpenFOAM (Open Field Operation and Manipulation) is a free, open-source CFD toolbox
written in C++. It solves complex fluid flows involving chemical reactions, turbulence,
heat transfer, acoustics, solid dynamics, and electromagnetics using the Finite Volume
Method (FVM).

**Key Capabilities for Hydraulics:**
- Incompressible and compressible flow (Navier-Stokes equations)
- Free-surface flows via Volume of Fluid (VoF) method (`interFoam` / `incompressibleVoF`)
- Multiphase Eulerian and Lagrangian particle tracking
- Turbulence: RANS (k-epsilon, k-omega SST, Spalart-Allmaras), LES, DES, DNS
- Adaptive mesh refinement and dynamic mesh motion
- Fully parallelized via MPI domain decomposition

**Architecture (dev version):**
The development version uses a modular solver architecture where `foamRun` dynamically
loads solver modules (e.g., `incompressibleFluid`, `fluid`, `incompressibleVoF`). Legacy
solver binaries (`simpleFoam`, `icoFoam`, `interFoam`) are thin wrappers calling `foamRun`.

---

## 2. Installation

### 2.1 Prerequisites
- C++ compiler: GCC >= 7, Clang, or Intel
- MPI: OpenMPI or MPICH (for parallel runs)
- Scotch or METIS (mesh partitioning)
- flex (lexer generator)
- ParaView (optional, for visualization)

### 2.2 Build from Source
```bash
# Clone repository
git clone https://github.com/OpenFOAM/OpenFOAM-dev.git OpenFOAM-dev

# Source environment
cd OpenFOAM-dev
source etc/bashrc

# Build everything (libraries + solvers + utilities)
./Allwmake -j$(nproc) 2>&1 | tee log.Allwmake

# Verify
blockMesh -help
foamRun -help
```

### 2.3 Environment Variables
| Variable | Purpose |
|----------|---------|
| `WM_PROJECT_DIR` | Root of OpenFOAM installation |
| `FOAM_APPBIN` | Compiled executables |
| `FOAM_LIBBIN` | Compiled libraries |
| `FOAM_TUTORIALS` | Tutorial case directory |
| `WM_COMPILER` | Compiler selection (Gcc, Clang) |
| `WM_ARCH_OPTION` | 32 or 64 bit addressing |

### 2.4 Test Installation
```bash
mkdir -p $FOAM_RUN && cd $FOAM_RUN
cp -r $FOAM_TUTORIALS/incompressibleFluid/cavity .
cd cavity
blockMesh
foamRun
```

---

## 3. Case Directory Structure

Every OpenFOAM simulation is defined by a case directory:

```
caseDir/
+-- 0/                  # Initial and boundary conditions
|   +-- p               # Pressure field
|   +-- U               # Velocity field
|   +-- k               # Turbulent kinetic energy (if turbulent)
|   +-- epsilon          # Turbulent dissipation (if turbulent)
+-- constant/           # Time-invariant properties
|   +-- polyMesh/       # Mesh definition (generated)
|   |   +-- points      # Vertex coordinates
|   |   +-- faces       # Face definitions
|   |   +-- owner       # Face-to-cell ownership
|   |   +-- neighbour   # Face-to-cell adjacency
|   |   +-- boundary    # Patch definitions
|   +-- physicalProperties   # Fluid viscosity, density
|   +-- momentumTransport    # Turbulence model config
+-- system/             # Solver configuration
    +-- controlDict     # Time stepping, write control, solver
    +-- fvSchemes       # Discretization schemes
    +-- fvSolution      # Linear solver settings, PIMPLE config
    +-- blockMeshDict   # Mesh generation parameters
    +-- decomposeParDict # Parallel decomposition
```

---

## 4. Pipeline Stages

| # | Stage | Tool | Description | Depends On |
|---|-------|------|-------------|------------|
| s0 | Configuration | `configure_case.py` | Set domain extents, fluid properties, time parameters | - |
| s1 | Mesh Generation | `generate_mesh.py` | Create computational mesh from blockMeshDict or external geometry | s0 |
| s2 | Boundary Conditions | `convert_forcing_to_openfoam.py` | Convert forcing data (velocity, pressure) to OpenFOAM field format | s1 |
| s3 | Physical Properties | `convert_properties_to_openfoam.py` | Convert fluid/soil properties to OpenFOAM dictionaries | s0 |
| s4 | Solver Setup | (manual) | Configure fvSchemes, fvSolution, controlDict | s1, s2, s3 |
| s5 | Execution | `run_openfoam.py` | Run solver binary with monitoring | s4 |
| s6 | Post-processing | `parse_openfoam_output.py` | Extract time series, fields to CSV/VTK | s5 |
| s7 | Visualization | (ParaView / matplotlib) | Create figures from extracted data | s6 |

---

## 5. Input Formats and Units

### 5.1 FoamFile Header (all field/dictionary files)
```cpp
FoamFile
{
    format      ascii;              // ascii or binary
    class       volScalarField;     // field type
    location    "0";                // time directory
    object      p;                  // field name
}
```

### 5.2 Dimension Array
OpenFOAM enforces dimensional consistency via a 7-element array:
```
dimensions [kg  m  s  K  mol  A  cd]
           [M   L  T  Th N    J  Lum]
```

| Quantity | Dimension Array | SI Unit |
|----------|----------------|---------|
| Pressure (kinematic) | `[0 2 -2 0 0 0 0]` | m^2/s^2 |
| Pressure (dynamic) | `[1 -1 -2 0 0 0 0]` | Pa |
| Velocity | `[0 1 -1 0 0 0 0]` | m/s |
| Kinematic viscosity | `[0 2 -1 0 0 0 0]` | m^2/s |
| Dynamic viscosity | `[1 -1 -1 0 0 0 0]` | Pa.s |
| Density | `[1 -3 0 0 0 0 0]` | kg/m^3 |
| Temperature | `[0 0 0 1 0 0 0]` | K |
| Turbulent kinetic energy | `[0 2 -2 0 0 0 0]` | m^2/s^2 |
| Turbulent dissipation | `[0 2 -3 0 0 0 0]` | m^2/s^3 |
| Volumetric flux (phi) | `[0 3 -1 0 0 0 0]` | m^3/s |
| Mass flux | `[1 0 -1 0 0 0 0]` | kg/s |
| Surface tension | `[1 0 -2 0 0 0 0]` | kg/s^2 |

### 5.3 Boundary Condition Types
| BC Type | Usage | Key Parameters |
|---------|-------|----------------|
| `fixedValue` | Dirichlet (fixed value) | `value uniform (Ux Uy Uz)` |
| `zeroGradient` | Neumann (zero flux) | none |
| `inletOutlet` | Switches on flow direction | `inletValue`, `value` |
| `totalPressure` | Total pressure inlet | `p0`, `gamma` |
| `noSlip` | Wall no-slip (velocity) | none |
| `slip` | Free-slip wall | none |
| `empty` | 2D simulation (ignored direction) | none |
| `symmetry` | Symmetry plane | none |
| `wedge` | Axisymmetric 2D | none |
| `cyclic` | Periodic | `neighbourPatch` |
| `fixedFluxPressure` | Pressure for fixed-velocity walls | `value` |

---

## 6. Unit Trap Table

These are the most dangerous unit/format traps that cause silent errors or crashes:

| ID | Trap | Expected | Common Mistake | Consequence |
|----|------|----------|----------------|-------------|
| ut_001 | Kinematic vs dynamic pressure | `[0 2 -2 0 0 0 0]` for incompressible | Using Pa `[1 -1 -2 0 0 0 0]` | Dimension mismatch crash |
| ut_002 | Kinematic viscosity `nu` | m^2/s (e.g., 1e-6 for water) | Using dynamic viscosity mu in Pa.s | Velocities off by density factor |
| ut_003 | blockMesh `convertToMeters` | Applied to all vertex coords | Forgetting scale factor (mm vs m) | Mesh 1000x too large/small |
| ut_004 | Velocity inlet units | m/s always | Using cm/s or mm/s | Flow rate off by orders of magnitude |
| ut_005 | Time step `deltaT` vs Courant | Courant = U*dt/dx < 1 | Too large dt for mesh | Divergence, floating point overflow |
| ut_006 | Turbulence inlet values | k = 1.5*(U*I)^2, eps = Cmu*k^1.5/l | Wrong turbulence intensity I | Incorrect turbulent profiles |
| ut_007 | Gravity vector | (0 -9.81 0) or (0 0 -9.81) | Wrong sign or axis | Buoyancy reversed |
| ut_008 | `writeInterval` interpretation | Depends on `writeControl` | `timeStep` vs `runTime` confusion | Too many/few output files |
| ut_009 | Parallel decomposition | `numberOfSubdomains` must match `mpirun -np N` | Mismatch between dict and CLI | MPI crash at startup |
| ut_010 | Boundary patch names | Must match blockMeshDict names exactly | Typo or case mismatch | Unassigned patch, crash |
| ut_011 | `internalField uniform 0` for vectors | Must be `uniform (0 0 0)` | Scalar 0 for vector field | Parse error |
| ut_012 | Surface tension `sigma` in VoF | `[1 0 -2 0 0 0 0]` (kg/s^2) | Using N/m as scalar without dimensions | Wrong interface dynamics |

---

## 7. Solver Reference

### 7.1 Key Solvers (foamRun modules)
| Module | Physics | Typical Use |
|--------|---------|-------------|
| `incompressibleFluid` | Incompressible Navier-Stokes | Pipe flow, channel flow, external aero |
| `fluid` | General compressible/thermal | HVAC, heat exchangers |
| `isothermalFluid` | Compressible, no energy eq | Gas dynamics |
| `incompressibleVoF` | Two-phase VoF | Free surface, wave, dam break |
| `compressibleVoF` | Two-phase VoF + compressibility | Cavitation |
| `multiphaseEuler` | N-phase Eulerian | Bubble columns, fluidized beds |
| `incompressibleDriftFlux` | Drift flux mixture | Slurry, sediment transport |
| `solid` | Heat conduction in solids | Conjugate heat transfer |
| `solidDisplacement` | Structural mechanics | FSI coupling |

### 7.2 Key Utilities
| Utility | Purpose |
|---------|---------|
| `blockMesh` | Structured hex mesh generation |
| `snappyHexMesh` | Automated unstructured meshing |
| `decomposePar` | Domain decomposition for parallel |
| `reconstructPar` | Merge parallel results |
| `foamToVTK` | Export to VTK for ParaView |
| `postProcess` | Run function objects post-hoc |
| `checkMesh` | Mesh quality validation |
| `mapFields` | Interpolate fields between meshes |

### 7.3 PIMPLE Algorithm Settings
```cpp
PIMPLE
{
    nOuterCorrectors    50;     // Outer PIMPLE loops (1=PISO, >1=PIMPLE)
    nCorrectors         2;      // Pressure correction steps per outer
    nNonOrthogonalCorrectors 1; // Non-orthogonal correction
    pRefCell            0;      // Reference cell for pressure
    pRefValue           0;      // Reference pressure value
    residualControl
    {
        U               1e-5;   // Convergence criterion
        p               1e-5;
    }
}
```

---

## 8. Critical Domain Knowledge

### dk_001: Kinematic vs Dynamic Pressure
OpenFOAM's incompressible solvers use **kinematic pressure** p/rho with dimensions
`[0 2 -2 0 0 0 0]` (m^2/s^2), NOT dynamic pressure in Pascal. When coupling with
external tools that output Pa, you MUST divide by density. This is the single most
common source of error for new users.

### dk_002: convertToMeters in blockMeshDict
The `convertToMeters` factor is applied to ALL vertex coordinates. If your vertices
are already in meters, set it to 1. If vertices are in millimeters, set 0.001.
Forgetting this produces a mesh at the wrong scale -- all velocities and Reynolds
numbers will be wrong, but the simulation may still converge, producing silently
incorrect results.

### dk_003: Boundary Patch Consistency
Patch names in `0/U`, `0/p`, etc. MUST exactly match those defined in
`constant/polyMesh/boundary` (generated by blockMesh/snappyHexMesh). A single
character mismatch causes a fatal "patch not found" error. After regenerating the
mesh, always update boundary condition files.

### dk_004: Courant Number and Time Stepping
For explicit or semi-implicit time schemes, the Courant number Co = U*dt/dx must
remain below ~1. Use `adjustTimeStep yes` with `maxCo 1` in controlDict for
adaptive stepping. For steady-state (SIMPLE), this does not apply -- use large
pseudo-time steps instead.

### dk_005: Gravity Direction in Hydraulic Simulations
For free-surface flows (VoF), gravity MUST be defined in `constant/g` as a
`uniformDimensionedVectorField`. The standard convention is `(0 -9.81 0)` for
Y-up or `(0 0 -9.81)` for Z-up. Using the wrong axis or sign produces inverted
buoyancy -- heavy fluid rises, light fluid sinks.

### dk_006: Turbulence Model Initialization
Under-initialized turbulence fields (k, epsilon, omega) cause the first few
iterations to diverge. Use the estimations:
- k = 1.5 * (U_ref * TI)^2  where TI = turbulence intensity (typically 0.01-0.1)
- epsilon = C_mu^0.75 * k^1.5 / l  where l = characteristic length scale
- omega = k^0.5 / (C_mu^0.25 * l)

### dk_007: writeControl vs writeInterval Semantics
- `writeControl timeStep; writeInterval 100;` writes every 100 time steps
- `writeControl runTime; writeInterval 0.1;` writes every 0.1 seconds of simulation time
- `writeControl adjustableRunTime;` adjusts dt to hit exact write times
Mixing these up produces unexpected output frequency.

### dk_008: VoF Phase Fraction alpha
In VoF simulations, `alpha.water` (or `alpha.phase1`) ranges 0-1. The field must
be initialized correctly: 1 = water, 0 = air. Using `setFields` with `boxToCell`
or `cylinderToCell` is required. An all-zero alpha field means no water exists.

### dk_009: Parallel Run MPI Consistency
`mpirun -np N foamRun -parallel` requires:
1. `system/decomposeParDict` with `numberOfSubdomains N;`
2. `decomposePar` run first to create `processor0/` ... `processorN-1/` directories
3. The N values MUST match. A mismatch causes immediate MPI abort.

---

## 9. Calibration and Tuning Parameters

| Parameter | Location | Range | Controls | Sensitivity |
|-----------|----------|-------|----------|-------------|
| `nu` (kinematic viscosity) | physicalProperties | 1e-7 to 1e-3 m^2/s | Reynolds number | High |
| `deltaT` | controlDict | 1e-6 to 1 s | Temporal resolution | High |
| `nOuterCorrectors` | fvSolution/PIMPLE | 1-100 | Coupling convergence | Medium |
| `nCorrectors` | fvSolution/PIMPLE | 1-4 | Pressure accuracy | Medium |
| `relaxationFactors` | fvSolution | 0.1-1.0 | Stability vs speed | High |
| `turbulence intensity` | 0/k inlet | 0.01-0.10 | Inlet turbulence level | Medium |
| `y+ (first cell height)` | blockMeshDict grading | 1-300 | Wall treatment accuracy | High |
| Convection scheme | fvSchemes/divSchemes | linearUpwind to QUICK | Numerical diffusion | Medium |
| `maxCo` | controlDict | 0.5-5.0 | Adaptive time step limit | High |
| `sigma` (surface tension) | physicalProperties | 0.01-0.1 N/m | VoF interface behavior | High (VoF) |

---

## 10. Data Requirements

| Data | Source | Format | Notes |
|------|--------|--------|-------|
| Domain geometry | CAD / GIS / manual | STL, blockMeshDict vertices | Meters (SI) |
| Fluid properties | Literature / measurement | physicalProperties dict | Kinematic viscosity, density |
| Inlet velocity | Measurement / design spec | 0/U fixedValue | m/s, vector (Ux Uy Uz) |
| Outlet pressure | Design / atmospheric | 0/p fixedValue/zeroGradient | m^2/s^2 (kinematic) |
| Turbulence BC | Estimation from Re | 0/k, 0/epsilon, 0/omega | Derived from U and length scale |
| Bathymetry (hydraulics) | DEM / survey | STL surface for snappyHexMesh | Must be watertight |
| Forcing (tidal, wave) | Tide tables / wave spectrum | Time-varying BC via coded/uniformFixedValue | m/s or m |

---

## 11. Quick Start

```bash
# 1. Source environment
source $WM_PROJECT_DIR/etc/bashrc

# 2. Copy tutorial case
cp -r $FOAM_TUTORIALS/incompressibleFluid/cavity myCase && cd myCase

# 3. Generate mesh
blockMesh

# 4. Check mesh quality
checkMesh

# 5. Run solver
foamRun

# 6. Convert output for visualization
foamToVTK

# 7. Parallel execution (4 cores)
decomposePar
mpirun -np 4 foamRun -parallel
reconstructPar
```

---

## 12. Output Format

### 12.1 Time Directories
Each write produces a directory named by the simulation time (e.g., `0.1/`, `0.2/`):
```
0.1/
+-- p           # Pressure field (all cells + boundaries)
+-- U           # Velocity field
+-- phi         # Face flux field
+-- uniform/    # Uniform fields (time info)
```

### 12.2 Field File Format
```cpp
internalField   nonuniform List<scalar>
1000            // number of cells
(
    0.0
    0.00123
    ...
)
;

boundaryField
{
    inlet { type calculated; value nonuniform List<scalar> 20 (...); }
    ...
}
```

### 12.3 Log File
The solver writes residuals, Courant number, and execution time to stdout.
Typical log line:
```
Time = 0.5
smoothSolver:  Solving for Ux, Initial residual = 0.00234, Final residual = 1.2e-07, No Iterations 3
GAMG:  Solving for p, Initial residual = 0.0156, Final residual = 4.5e-07, No Iterations 12
ExecutionTime = 1.23 s  ClockTime = 2 s
```

### 12.4 Function Objects
Post-processing probes, forces, and field averages are written to `postProcessing/`:
```
postProcessing/
+-- forces/
|   +-- 0/
|       +-- force.dat         # Time series of forces
+-- probes/
    +-- 0/
        +-- p                 # Probed pressure values
        +-- U                 # Probed velocity values
```

---

## 13. Coupling Points

| # | Interface | From | To | Data Exchanged |
|---|-----------|------|----|----------------|
| 1 | Mesh import | External CAD/GIS | OpenFOAM polyMesh | STL geometry, cell zones |
| 2 | Forcing BC | Hydrological model | OpenFOAM inlet | Discharge (m^3/s) -> velocity (m/s) |
| 3 | VoF init | DEM/bathymetry | alpha.water | Water surface elevation -> phase field |
| 4 | Output export | OpenFOAM fields | Downstream models | Velocity, pressure, WSE |
| 5 | Parallel | MPI decomposition | Multi-core execution | Domain partitioning |
| 6 | FSI | OpenFOAM fluid | OpenFOAM solid | Pressure on interface patches |

---

## 14. Diagnostic Triplets Summary

See `diagnostics/triplets.yaml` for full definitions.

| ID | Severity | Domain | Summary |
|----|----------|--------|---------|
| dt_001 | fatal | dimension_mismatch | Kinematic vs dynamic pressure dimensions |
| dt_002 | silent | unit_conversion | convertToMeters forgotten or wrong |
| dt_003 | fatal | patch_consistency | Boundary patch name mismatch |
| dt_004 | fatal | numerical_stability | Courant number exceeds limit |
| dt_005 | silent | unit_conversion | Gravity vector wrong axis or sign |
| dt_006 | degraded | initialization | Turbulence fields under-initialized |
| dt_007 | silent | configuration | writeControl/writeInterval mismatch |
| dt_008 | silent | initialization | VoF alpha field all zeros |
| dt_009 | fatal | parallel | MPI np vs decomposeParDict mismatch |
| dt_010 | fatal | mesh_quality | Non-orthogonality > 70 degrees |
| dt_011 | silent | unit_conversion | Dynamic viscosity used instead of kinematic |
| dt_012 | fatal | syntax | Scalar used for vector internalField |
| dt_013 | degraded | convergence | Relaxation factors too aggressive |
| dt_014 | silent | output | purgeWrite deleting needed time dirs |
| dt_015 | fatal | dependency | Missing MPI or Scotch at runtime |
| dt_016 | degraded | mesh_quality | y+ outside wall function valid range |
| dt_017 | silent | configuration | Empty functionObjects block |
| dt_018 | fatal | syntax | Missing semicolon in dictionary |
| dt_019 | silent | unit_conversion | Surface tension sigma wrong dimensions |
| dt_020 | degraded | convergence | Insufficient nNonOrthogonalCorrectors |

---

## 15. File Structure

```
ki/
+-- SKILL.md                    # This file
+-- tools/
|   +-- convert_forcing_to_openfoam.py    # Forcing/BC converter
|   +-- convert_properties_to_openfoam.py # Physical properties converter
|   +-- generate_mesh.py                  # Mesh generation wrapper
|   +-- run_openfoam.py                   # Execution wrapper
|   +-- parse_openfoam_output.py          # Output parser
|   +-- configure_case.py                 # Case configuration generator
|   +-- check_case.py                     # Pre-run validation
+-- docs/
|   +-- s0_configuration.md       # Case configuration skill
|   +-- s1_mesh_generation.md     # Mesh generation skill
|   +-- s2_boundary_conditions.md # Forcing/BC setup skill
|   +-- s3_physical_properties.md # Property configuration skill
|   +-- s4_solver_setup.md        # Solver and scheme selection skill
|   +-- s5_execution.md           # Running OpenFOAM skill
|   +-- s6_postprocessing.md      # Output analysis skill
+-- diagnostics/
    +-- triplets.yaml             # 20 diagnostic triplets
```