Back to skills
SKILL.md
OpenFOAM
ASecurity| Field | Value | |-------|-------| | Package | OpenFOAM-dev (CFD Framework) | | Domain | Computational Fluid Dynamics / Hydraulics / Storm Surge | | 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 | 32 (20 general + 12 ocean/storm-surge) | | Validation | cavity tutorial; Hurricane Laura 2020 IB barometric (NSE=0.51, R=0.84 @ Grand Isle...
- 200 stars
- 0 votes
- 0 copies
- 1 view
- Added September 11, 2026
Works with
Security analysis
100/100Pro scans all 20 files and shows the line behind each finding
npx -y skills add lzwei196/KISS---Knowledge-Infrastructure-for-Scientific-Simulation --skill OpenFOAM --agent claude-codeAre you the author of OpenFOAM?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/lzwei196-openfoam)> **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.
<!-- KI-MAP:BEGIN (projected by generate_skill_map.py — edit the KI, not this table) -->
## KI map — what to read, and when
| when you need | read | why |
|---|---|---|
| FIRST, always | `preflight_check.py` | run it (`python preflight_check.py`): proves env/binary/data are usable and emits a machine-readable `PREFLIGHT_REPORT=` line. Do not debug a run that never had a healthy environment. |
| to run the pipeline stages | `tools/` (7 tools) | the executable pipeline. Read each tool's argparse (`--help`) before composing a command; SKILL.md's stage table says which tool serves which stage. |
| before running a stage | `docs/s*_*.md` (8 stage docs) | per-stage procedure, verification and traps — the how-to that SKILL.md's overview compresses. |
| on ANY error, before debugging | `diagnostics/triplets.yaml` (32 entries) | symptom → diagnosis → remedy for this model's known failure modes. Check here FIRST; the answer usually exists. Never renumber or rewrite entries. |
| to know what an output IS | `dag.yaml` | the model's identity: every output's medium, units, `validation_rank` (1 = the headline variable) and observability. Scoring and obs-binding read THIS — when asked 'what does this model predict', the dag is the answer, not a guess. |
| when building inputs / parsing outputs | `docs/format_spec.yaml` | exact I/O shapes + `known_issues`, projected from dag + triplets. Regenerate with `ki_tools_common/generate_format_spec.py` after changing either — never hand-edit. |
| to judge a run's skill | `docs/validation_convention.yaml` | how this model's field judges it validated: per-`dag_variable` metrics, directions and CITED pass-bands. A run is graded against these, not against intuition. |
| for claims and thresholds | `docs/gathered_papers.json` (20 papers) + `docs/papers_index.md` | the literature this KI is judged by; each entry's `text_path` is fetched full text in the central paper cache. `role: benchmark` marks the model's own skill paper. |
| for a machine-readable summary | `knowledge_infrastructure.yaml` | the manifest (package, pipeline, validation tier, counts) — projected by `ki_tools_common/generate_ki_manifest.py`; regenerate after structural changes, never hand-edit. |
*Projected 2026-08-17 from the KI's actual contents — 9 components present. Refresh: `python3 ki_tools_common/generate_skill_map.py --ki_dir <this KI>`.*
<!-- KI-MAP:END -->
<!-- KI-TOOL-INDEX:BEGIN (projected by generate_skill_map.py — the discoverability contract: every public tool, exact path; PURPOSE stays human-authored elsewhere) -->
### Executable tool index (projected — complete by construction)
Every public tool in this KI, by exact path. What each is FOR lives in the
human-written Tool Inventory above; `--help` on any of these prints its arguments.
| tool (exact path) | invocation |
|---|---|
| `tools/check_case.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/check_case.py --help` |
| `tools/configure_case.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/configure_case.py --help` |
| `tools/convert_forcing_to_openfoam.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_forcing_to_openfoam.py --help` |
| `tools/convert_properties_to_openfoam.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/convert_properties_to_openfoam.py --help` |
| `tools/generate_mesh.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/generate_mesh.py --help` |
| `tools/parse_openfoam_output.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/parse_openfoam_output.py --help` |
| `tools/run_openfoam.py` | `KISSPATH_PYTHON_ENV/bin/python {KI}/tools/run_openfoam.py --help` |
*7 public tools; `_`-prefixed helpers and packaging files excluded.*
<!-- KI-TOOL-INDEX:END -->
# OpenFOAM Knowledge Infrastructure
| Field | Value |
|-------|-------|
| Package | OpenFOAM-dev (CFD Framework) |
| Domain | Computational Fluid Dynamics / Hydraulics / Storm Surge |
| 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 | 32 (20 general + 12 ocean/storm-surge) |
| Validation | cavity tutorial; Hurricane Laura 2020 IB barometric (NSE=0.51, R=0.84 @ Grand Isle) |
---
## 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. Output Description
This section restates `dag.yaml`; if this body ever disagrees with the dag, the dag wins.
**Headline output** (`validation_rank: 1`):
> `alpha.water` - VoF phase fraction; the iso-surface alpha=0.5 defines the free surface, from which water-level / wave elevation is derived. (dimensionless 0-1)
| Output variable (dag `var`) | Rank | File / location | Unit | Description |
|-----------------------------|------|-----------------|------|-------------|
| `alpha.water` | 1 | OpenFOAM time directory field | dimensionless 0-1 | VoF phase fraction; the iso-surface alpha=0.5 defines the free surface, from which water-level / wave elevation is derived. |
| `U` | not supplied in extracted facts | OpenFOAM time directory field | m/s | Velocity field. |
| `p` | not supplied in extracted facts | OpenFOAM time directory field | m^2/s^2 for incompressible kinematic pressure; Pa for dynamic pressure | Pressure field. |
| `phi` | not supplied in extracted facts | OpenFOAM time directory field | m^3/s for volumetric flux | Face flux field. |
| `k` | not supplied in extracted facts | OpenFOAM time directory field | m^2/s^2 | Turbulent kinetic energy field. |
Other dag outputs supplied by the KI facts are: `U`, `p`, `phi`, `k`.
---
## 8. Unit Conversion Table
Exact I/O shapes live in `docs/format_spec.yaml`. This body table restates the model units
and the conversions already documented in this KI; do not use it to override dag or format-spec facts.
| Variable | Source unit (verified) | Model/output unit | Conversion | Source in KI |
|----------|------------------------|-------------------|------------|--------------|
| `alpha.water` | dimensionless phase fraction | dimensionless 0-1 | none | `dag.yaml` |
| `U` | m/s | m/s | none when source velocity is already SI | SKILL.md dimension table |
| `p` | Pa from external dynamic-pressure tools | m^2/s^2 for incompressible kinematic pressure | divide by density | SKILL.md dimension table; `dk_001` |
| `phi` | m^3/s volumetric flux | m^3/s | none when source flux is already SI | SKILL.md dimension table |
| `k` | m^2/s^2 | m^2/s^2 | none | SKILL.md dimension table |
| Storm-surge inverted barometer forcing | mbar | m water-level response | eta_IB = -(Pair-1013.25)*100/(rho*g) | `ut_016` |
### 8.1 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 |
| ut_013 | Hydrostatic p_rgh init in VoF | p_rgh_water = p_atm_BC + (ρ_w-ρ_a)·g·z_surface | `uniform 0` or `uniform p_atm` | 400,000 Pa imbalance → 32 m/s spike → 4s deltaT forever |
| ut_014 | phaseProperties `sigma` (dev) | `sigma 0.07;` (scalar, no parens) | `sigmas ((air water) 0.07);` (legacy) | FATAL: "keyword sigma is undefined" |
| ut_015 | cAlpha in fvSolution (dev) | Removed — set via div(phi,alpha) in fvSchemes | `cAlpha 0.5;` in alpha.water solver block | FATAL: "Deprecated and unused cAlpha" |
| ut_016 | Storm surge IB formula | η_IB = −(Pair−1013.25)×100/(ρ×g) [mbar→m] | Omitting ×100 for mbar→Pa conversion | 100× too small surge |
| ut_017 | Free surface cell alignment | z_surface must equal a blockMesh cell face | z_surface inside a cell (e.g. 47.5m in 10m cells) | Max(alpha)=1.82 at t=0 → RT instability |
---
## 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_010: incompressibleVoF vs shallowWaterFoam for Ocean Domains
**incompressibleVoF is designed for lab-scale problems** (wave tank, ship waves, dam break).
It is NOT appropriate for basin-scale ocean/storm surge domains (>100 km horizontal) because:
1. **Mass loss**: MULES numerical diffusion smears alpha into the air cell layer; open atmosphere
BCs then let diffused alpha escape. At 40m depth with 10m cells, mass loss rate ~4.7e-7/s.
2. **Standing waves**: Closed slip-wall domain has no wave absorption. Initial pressure transients
create resonant gravity waves (period T = 2L/c ≈ 27 h for 977 km basin). deltaT permanently
oscillates at 0.25-1.5s — 100× slower than needed.
3. **Zero surge from uniform forcing**: Domain-averaged uniform p_atm has ∇p_atm = 0. The IB
surface rise is exactly cancelled by the p_rgh change at the gauge → net surge = 0.
4. **VoF scale constraint**: For a 977km × 674km × 50m domain, VoF must resolve both the
40m water column AND the 977km horizontal dynamics simultaneously — computationally intractable.
**Use shallowWaterFoam instead** (`$WM_PROJECT_DIR/applications/legacy/incompressible/shallowWaterFoam/`):
- Solves 2D depth-integrated SWE: ∂h/∂t + ∇·(hU) = 0; ∂(hU)/∂t + ∇·(UhU) + g·h·∇(h+h0) = 0
- Fields: h (depth), hU (depth-integrated velocity), h0 (bed topography)
- Typical dt = 0.5 × dx / √(g·h) = 0.5 × 4886 / √(9.81×40) = 123s → 4320 steps for 5 days
- Barometric forcing: set h0(x,y,t) = −(p_atm − p_ref)/(ρ·g) (inverted barometer)
- Reference performance: IB-only gives NSE=0.51, R=0.84 vs NOAA obs @ Grand Isle for Laura 2020
### dk_011: libparallel.so Must Be Built Before decomposePar
When building individual OpenFOAM utilities (not running Allwmake), the dependency
`libparallel.so` in `src/parallel/parallel/` must be compiled first or decomposePar
will fail with "cannot find -lparallel". Fix:
```bash
cd $WM_PROJECT_DIR/src/parallel/parallel && wmake libso
# Then retry decomposePar
```
### dk_012: MULESCorr yes Causes Rayleigh-Taylor Instability
`MULESCorr yes` (the MULES correction step) applies an additional corrective flux after
the bounded MULES step. This correction can overshoot, producing alpha > 1 in interface
cells. When alpha > 1 in an upper cell, that cell has density > ρ_water, sitting above
normal water → Rayleigh-Taylor unstable. The velocity grows exponentially until NaN.
**Always use `MULESCorr no` for large domains or when alpha Max > 1 is observed.**
`nSubCycles 1-2` is sufficient; `nSubCycles 5` with `MULESCorr no` is stable but slow.
### dk_013: runTimeModifiable Does Not Apply to 0/ Field Files
`runTimeModifiable true` in controlDict allows hot-editing of `system/fvSchemes`,
`system/fvSolution`, and `system/controlDict`. It does NOT re-read boundary conditions
from `0/` field files. For a running parallel case, BC changes must be made to ALL
`processor*/0/fieldName` files and require a solver restart.
### dk_014: Water Level Extraction from p_rgh Probe (VoF)
For an incompressibleVoF storm surge simulation, the water level anomaly at a gauge
located at height z_probe (within the water column) is:
```
η(t) = (p_rgh_probe(t) − p_rgh_probe(0)) / ((ρ_water − ρ_air) × g)
```
This only gives correct surge if: (a) mass is conserved (no alpha leakage), AND
(b) the forcing has spatial variation at the gauge location (∇p_atm ≠ 0).
With uniform domain-averaged forcing: the IB rise and p_rgh change cancel → η = 0.
### 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. Validated Results
This section restates the KI's validation facts and `docs/validation_convention.yaml`
convention bars. A missing/null convention band is written as "no cited threshold";
no threshold is inferred.
### Recorded Validation Cases
| Case | Metric / result | Location | Notes |
|------|-----------------|----------|-------|
| cavity tutorial | not supplied in extracted facts | not supplied in extracted facts | Listed in the KI validation summary. |
| Hurricane Laura 2020 IB barometric | NSE=0.51, R=0.84 | Grand Isle | Listed in the KI validation summary. |
### Performance Metrics -- judged against the field's bar, not intuition
No convention bar for the rank-1 dag output `alpha.water` was supplied in the extracted
validation-convention facts. The available convention bars supplied by the KI are:
| Dag variable | Metric | Direction | Very good band | Good band | Satisfactory band |
|--------------|--------|-----------|----------------|-----------|-------------------|
| `U` | rmse | minimize | 0.05 (hydro_guidance2017) | 0.1 (hydro_guidance2017) | 0.2 (hydro_guidance2017) |
| `U` | bias | zero_centered | no cited threshold (hydro_guidance2017) | no cited threshold (hydro_guidance2017) | 0.2 (hydro_guidance2017) |
| `U` | rmse | minimize | 0.05 (hydro_guidance2017) | 0.1 (hydro_guidance2017) | 0.2 (hydro_guidance2017) |
| `U` | scatter_index | minimize | no cited threshold (hydro_guidance2017) | no cited threshold (hydro_guidance2017) | 0.5 (hydro_guidance2017) |
| `p` | nse | maximize | no cited threshold (no citation key in convention) | no cited threshold (no citation key in convention) | no cited threshold (no citation key in convention) |
| `p` | comparison_error | minimize | no cited threshold (no citation key in convention) | no cited threshold (no citation key in convention) | no cited threshold (no citation key in convention) |
### Achieved Metrics Against Convention Bars
| Case | Metric | Achieved | Convention bar |
|------|--------|----------|----------------|
| Hurricane Laura 2020 IB barometric | NSE | 0.51 | `p` nse has no cited threshold (no citation key in convention). |
| Hurricane Laura 2020 IB barometric | R | 0.84 | no convention bar supplied in extracted facts. |
### Data Replacement Tracking
| Component | Source | Status | Notes |
|-----------|--------|--------|-------|
| Forcing | Pipeline | pending | Use `docs/format_spec.yaml` and stage docs for exact inputs before scoring. |
| Initial conditions | Pipeline | pending | VoF `alpha.water` initialization controls the rank-1 observable. |
| Outputs | OpenFOAM time directories / parser | pending | Score against `docs/validation_convention.yaml`, not intuition. |
---
## 12. 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
```
---
## 13. Output Format
### 13.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)
```
### 13.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 (...); }
...
}
```
### 13.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
```
### 13.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
```
---
## 14. 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 |
---
## 15. 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 |
| dt_021 | silent | solver_selection | incompressibleVoF used for basin-scale ocean surge (>100km) — mass loss + zero signal |
| dt_022 | fatal | numerical_stability | deltaT → machine-zero from MULESCorr alpha>1 Rayleigh-Taylor instability |
| dt_023 | fatal | numerical_stability | Fixed U + fixed p_rgh at same boundary (atmosphere) is overdetermined |
| dt_024 | fatal | library_dependency | decomposePar build fails: libparallel.so not built yet |
| dt_025 | silent | initialization | alpha.water inletOutlet at atmosphere causes mass loss via MULES diffusion |
| dt_026 | fatal | configuration | cAlpha deprecated in OpenFOAM-dev fvSolution alpha block |
| dt_027 | degraded | initialization | Free surface not aligned with cell face → setFields alpha overshoot > 1 |
| dt_028 | silent | initialization | Uniform p_rgh=0 init → 400kPa imbalance → standing waves → deltaT stuck at 0.25s |
| dt_029 | fatal | numerical_stability | Open lateral BCs (zeroGradient p_rgh) → hydrostatic pressure drives 28 m/s outflow |
| dt_030 | degraded | numerical_stability | interfaceCompression scheme creates periodic Co spikes that collapse deltaT |
| dt_031 | silent | output_interpretation | p_rgh gauge masked by mass loss; uniform forcing gives zero spatial surge variation |
| dt_032 | fatal | configuration | Dev incompressibleVoF requires phaseProperties + physicalProperties.water/air (not transportProperties) |
---
## 16. 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
```
Files in this skill
- SKILL.md
- dag.yaml
- diagnostics/triplets.yaml
- docs/REFERENCES.md
- docs/format_spec.yaml
- docs/papers.json
- docs/s0_configuration.md
- docs/s1_mesh_generation.md
- docs/s2_boundary_conditions.md
- docs/s3_physical_properties.md
- docs/s4_solver_setup.md
- docs/s5_execution.md
- docs/s6_postprocessing.md
- docs/s7_validation.md
- docs/validation_convention.yaml
- knowledge_infrastructure.yaml
- preflight_check.py
- tools/check_case.py
- tools/configure_case.py
- tools/convert_forcing_to_openfoam.py
Attribution
Comments
Loading comments…