Imported from lzwei196/KISS-Knowledge-Infrastructure-for-Scientific-Simulation (
models/OpenFOAM/SKILL.md). Install upstream withnpx skills add lzwei196/KISS-Knowledge-Infrastructure-for-Scientific-Simulation --skill OpenFOAM. Copyright stays with the author.
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:
- Check
diagnostics/triplets.yamlfor a matching error pattern- Try the fix suggested in the triplet's
remedysection- 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:
- Check triplets —
diagnostics/triplets.yamlmay already cover this error- Read official docs — The model's own documentation for expected formats/units
- Find working examples — Check
outputs/or the model's shipped test data- 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 — 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>.
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.
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
# 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
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)
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/(rhog) | 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*(UI)^2, eps = Cmuk^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
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 stepswriteControl runTime; writeInterval 0.1;writes every 0.1 seconds of simulation timewriteControl 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:
- 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.
- 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.
- 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.
- 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:
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:
system/decomposeParDictwithnumberOfSubdomains N;decomposeParrun first to createprocessor0/...processorN-1/directories- 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
# 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
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