Skip to content

OpenFOAM toolkit

Overall design

The OpenFOAM toolkit uses composition over inheritanceOFToolkit contains solver extensions, preprocessing objects, and post-processing pipelines as pluggable attributes rather than subclasses.

OFToolkit (hermesWorkflowToolkit)
├── OFObjectHome          — field definitions and creation
├── Analysis              — VTK post-processing pipeline
├── Presentation          — output formats (CSV, VTK)
├── Solver extensions (composition):
│   ├── simpleFoam_toolkitExtension
│   ├── buoyantReactingFoam_toolkitExtension
│   └── StochasticLagrangianSolver_toolkitExtension
│       └── OFLSMToolkit  — LSM coupling
└── Workflows (Hermes-integrated):
    ├── workflow_Eulerian
    │   ├── workflow_simpleFoam
    │   ├── workflow_buoyantReactingFoam
    │   ├── workflow_scalarTransportFoam
    │   ├── workflow_indoorFOAMBoussinesq
    │   └── workflow_homogenousWindLogProfile
    └── workflow_Lagrangian
        └── workflow_StochasticLagrangianSolver

OFToolkit (toolkit.py)

The main class inherits from hermesWorkflowToolkit for workflow support and composes all other components:

Attribute Type Purpose
OFObjectHome OFObjectHome Field definitions catalog and field creation
analysis Analysis VTK pipeline and data extraction
presentation Presentation Output to CSV, VTK, parquet
stochasticLagrangian StochasticLagrangianSolver_toolkitExtension Lagrangian particle tracking
buoyantReactingFoam buoyantReactingFoam_toolkitExtension Compressible reactive solver

Flow type constants:

Constant Value Used for
FLOWTYPE_INCOMPRESSIBLE simpleFoam, wind profile simulations
FLOWTYPE_COMPRESSIBLE buoyantReactingFoam
FLOWTYPE_DISPERSION Lagrangian particle dispersion

Key methods:

Method Description
createEmptyCase(caseDirectory, fieldList, flowType) Initialize OpenFOAM case directory structure
writeEmptyField(fieldName, flowType, caseDirectory, ...) Create empty field files with correct dimensions
getMesh(caseDirectory) Read cell centers (runs foamJob postProcess)
getMeshExtent(caseDirectory) Get bounding box from points file
runOFSimulation(nameOrWorkflowFileOrJSONOrResource) Build and execute full simulation via workflow
prepareSlurmWorkflowExecution(...) Generate Slurm batch submission scripts
getTimeList(...) Extract computed time steps from case
getVTKPipelineCacheTable(...) Query cached VTK filter results

Nested classes:

Class Methods Purpose
Analysis getVTKPipeline(), executeVTKFiltersAndLoad(), getFiltersDocuments() Create and run VTK filter pipelines
Presentation to_paraview_CSV(), toUnstructuredVTK(), toStructuredVTK(), loadLagrangianDataParallel() Export results in various formats

Workflow system (OFWorkflow.py)

Workflows define the steps to build and run an OpenFOAM case. They integrate with the Hermes framework.

Workflow hierarchy:

Class Inherits from Nodes
abstractWorkflow hermes.workflow controlDict, fvSolution, fvSchemes, fileWriter, Parameters
workflow_Eulerian abstractWorkflow + blockMesh, optional snappyHexMesh
workflow_Lagrangian abstractWorkflow Base for particle simulations
workflow_simpleFoam workflow_Eulerian Steady incompressible
workflow_buoyantReactingFoam workflow_Eulerian Compressible reacting
workflow_scalarTransportFoam workflow_Eulerian Scalar transport
workflow_indoorFOAMBoussinesq workflow_Eulerian Indoor Boussinesq approximation
workflow_homogenousWindLogProfile workflow_Eulerian Log-law wind profile
workflow_StochasticLagrangianSolver workflow_Lagrangian Stochastic Lagrangian dispersion

workflow_Eulerian key methods:

Method Description
prepareICandBC(configurationFile) Set initial and boundary conditions from config
set_blockMesh_blockBoundaries(...) Configure block mesh vertices and boundaries
set_blockMesh_blockHeight(...) Adjust domain height
ICandBCHandler_node(icnode) Process IC/BC node entries

Eulerian solver extensions (eulerian/)

Solver extensions are composed into OFToolkit as attributes. They handle solver-specific case setup.

Class Solver Properties
absractEulerianSolver_toolkitExtension (base) solverName, incompressible, flowType, analysis, presentation
simpleFoam_toolkitExtension simpleFOAM incompressible=True
buoyantReactingFoam_toolkitExtension buoyantReactingFoam incompressible=False

Key methods on the abstract solver:

Method Description
blockMesh_setBoundFromBounds(wf, minx, maxx, ...) Configure mesh boundaries from coordinates
blockMesh_setBoundFromFile(wf, fileName, dx, dy, dz) Configure mesh from OBJ geometry file
blockMesh_setDomainHeight(wf, Z, dz) Adjust vertical extent
writeFieldInCase(fieldName, caseDirectory, ...) Write a field file to the case
IC_getHydrostaticPressure(caseDirectory) Generate hydrostatic pressure initial condition

Lagrangian solver extensions (lagrangian/)

Hierarchy:

Class Purpose
absractStochasticLagrangianSolver_toolkitExtension Base for Lagrangian solvers — dispersion flow fields, source generation
StochasticLagrangianSolver_toolkitExtension Concrete implementation with default fields (ustar, distanceFromWalls)
OFLSMToolkit OpenFOAM + LSM coupling — particle data loading, concentration calculation

Abstract Lagrangian solver key methods:

Method Description
createDispersionFlowField(flowName, flowData, ...) Create flow field for dispersion (links to original flow, maps time steps, writes ustar/Hmix)
createDispersionCaseDirectory(hermes_dispersionWorkflow, ...) Set up dispersion case with processor links and DB sync
makeSource_Point/Circle/Sphere/Cylinder/Rectangle/Cube(...) Generate particle source geometries
writeParticlePositionFile(x, y, z, nParticles, ...) Write particle initial positions

OFLSMToolkit (lagrangian/LSM/toolkit.py):

Inherits from abstractToolkit (not from OFToolkit) and provides OpenFOAM + LSM coupling:

Property Description
casePath OpenFOAM case directory
cloudName Lagrangian particle cloud name
parallelCase Decomposed (parallel) case flag
sourcesFactory sourcesFactoryTool for source geometries
topography GIS topography toolkit reference
Method Description
loadData(times, saveMode, withVelocity, ...) Extract particle positions/velocities/masses as dask DataFrame
makeDistanceFromGround(times, ground, ...) Compute ground distance field
makeUstar(times, ...) Compute friction velocity field
to_paraview_CSV(data, ...) Export particles as timestep CSV
toUnstructuredVTK(data, ...) Export as VTU particle files
toStructuredVTK(data, ...) Export as structured VTK grid

Analysis inner class on OFLSMToolkit:

Method Description
calcConcentrationPointWise(data, dxdydz, ...) Cell-binned concentration from particle data
calcDocumentConcentrationPointWise(dataDocument, ...) Same with DB caching
calcConcentrationTimeStepFullMesh(...) Full domain regular grid concentration

Preprocessing objects (preprocessOFObjects/)

The preprocessing system provides an abstraction for OpenFOAM field files:

Class Purpose
OFObject Abstract base — field name, dimensions, regions (internalField/boundaryField), write to disk
OFField(OFObject) Concrete field — initialize empty, set uniform values, add boundaries, read from case, convert to DataFrame
OFObjectHome Field catalog — predefined fields (U, p, k, epsilon, T, ...) with correct dimensions for incompressible/compressible flows

OFObjectHome predefined fields: U, p, p_rgh, epsilon, omega, alphat, nut, k, T, Tbackground, cellCenters, Hmix, ustar, distanceFromWalls

Key OFObjectHome methods:

Method Description
getEmptyField(fieldName, flowType, noOfProc) Create empty field with correct dimensions
getEmptyFieldFromCase(fieldName, flowType, caseDirectory, ...) Create field pre-loaded with boundaries from an existing case
readFieldFromCase(fieldName, flowType, caseDirectory, timeStep) Read complete field data
readFieldAsDataFrame(fieldName, caseDirectory, times, ...) Read field across multiple time steps as DataFrame
addFieldDefinitions(fieldName, dimensions, fieldType, ...) Register custom field definitions

VTK post-processing pipeline (postProcess/)

The VTK pipeline provides a ParaView-integrated post-processing system with DB caching.

Pipeline architecture:

Class Purpose
VTKPipeLine Pipeline container — creates/manages filters, exports to JSON
registeredVTKPipeLine Pipeline bound to a specific case — executes filters, caches results
VTKFilter Base filter node — tree structure with downstream children
VTKPipelineExecutionContext Reader and pipeline configuration for paraview execution
paraviewOpenFOAM (pvOpenFOAMBase.py) ParaView backend — reads OpenFOAM cases, writes results

Available filters:

Filter class Type constant Purpose
vtkFilter_Slice FILTER_SLICE Planar slice through the domain
vtkFilter_PlotOverLine FILTER_PLOTOVERLINE Sample along a line
vtkFilter_CellCenters FILTER_CELLCENTERS Extract cell center values
vtkFilter_ExtractBlock FILTER_EXTRACTBLOCK Extract specific mesh regions/patches
vtkFilter_DescriptiveStatistics Compute summary statistics
vtkFilter_IntegrateVariables FILTER_INTEGRATEVARIABLES Integrate fields over domain

Data flow:

VTKPipeLine.registerPipeline(case)
    → registeredVTKPipeLine
        → getData(filterName, timeList, ...)
            → checks DB cache
            → if miss: runs ParaView pipeline
            → saves to parquet (non-regular) or ZARR (regular mesh)
            → stores metadata document in DB
            → returns dict of filter results

Filter tree: Filters form a tree — each filter can have downstream children. The pipeline traverses the tree depth-first, executing each filter and optionally writing results to disk.

Template system

Templates are saved OpenFOAM case directories stored as data sources. The toolkit provides: - saveTemplate(templateName, caseDirectory) — save a case as a template - loadTemplate(templateName, toDirectory, caseName) — instantiate a template