Developer Quickstart Documentation: foampilot Module
1. Introduction
The foampilot module is designed to simplify and automate the creation, configuration, execution, and post-processing of simulation cases based on OpenFOAM. It provides an object-oriented Python interface to manage complex OpenFOAM configuration files, allowing developers to focus on the physics and geometry of the problem rather than dictionary syntax.
This documentation aims to give a detailed overview of the code structure to facilitate understanding and contribution to the project.
2. Key Concepts and Architecture
The architecture of foampilot closely mirrors the structure of a standard OpenFOAM case, which is divided into three main directories: constant, system, and the initial time directory (0).
Central Class: Solver
The Solver class (foampilot.solver.Solver) is the central orchestrator of the module. It encapsulates the entire simulation case and provides access points to the constant and system directories, as well as boundary condition management.
Upon initialization, a Solver instance automatically creates objects needed to manage configuration files:
solver.constant: An instance ofConstantDirectoryto manage files in theconstantdirectory.solver.system: An instance ofSystemDirectoryto manage files in thesystemdirectory.solver.boundary: An instance ofBoundaryto manage boundary conditions.
3. Detailed Code Structure
The core logic of foampilot is located in the foampilot/foampilot/src/foampilot directory. This directory is organized into logical submodules, each responsible for a specific aspect of OpenFOAM case management.
| Source Directory | Description | Key Classes (Examples) |
|---|---|---|
base |
Base classes and utilities for OpenFOAM file handling. | Meshing, OpenFOAMFile |
solver |
Contains the main Solver class and simulation execution logic. |
Solver, BaseSolver |
constant |
Manages configuration files in the constant directory. |
ConstantDirectory, transportPropertiesFile, turbulencePropertiesFile |
system |
Manages configuration files in the system directory. |
SystemDirectory, controlDictFile, fvSchemesFile, fvSolutionFile |
boundaries |
Defines and applies boundary conditions. | Boundary, boundaries_conditions_config |
mesh |
Mesh tools, including integration with classy_blocks and snappyHexMesh. |
BlockMeshFile, Meshing, gmsh_mesher |
utilities |
Utility functions and classes not specific to OpenFOAM (units, fluid properties, etc.). | Quantity, FluidMechanics, manageunits |
postprocess |
Classes for result analysis, visualization (via pyvista), and data extraction. |
FoamPostProcessing, ResidualsPost |
4. Internal Mechanisms for Developers
For effective contribution, it is essential to understand how foampilot translates Python objects into OpenFOAM files and manages complex configurations.
4.1. File Writing Mechanism (OpenFOAMFile)
The core of data serialization lies in the base class OpenFOAMFile (foampilot/foampilot/src/foampilot/base/openFOAMFile.py).
- Inheritance and Attributes: Each OpenFOAM configuration file (e.g.,
transportPropertiesFileorcontrolDictFile) inherits fromOpenFOAMFile. Configuration parameters are stored in the instance attributeself.attributes. - Dynamic Access: Overriding magic methods
__getattr__and__setattr__allows direct access and modification of parameters as object attributes (e.g.,solver.constant.transportProperties.nu = ...), even if they are stored in theself.attributesdictionary. - Serialization (
write_file): Thewrite_filemethod recursively iterates overself.attributesand uses the internal_format_valuemethod to convert Python data types (booleans, numbers, tuples, especiallyQuantity) into OpenFOAM-specific syntax (e.g.,true/false, parenthesis-enclosed lists).
4.2. Unit and Dimension Management (Quantity)
The Quantity class (foampilot/foampilot/src/foampilot/utilities/manageunits.py) is a wrapper around the pint library and ensures physical consistency.
- Purpose: Stores a numerical value with its physical unit (e.g.,
Quantity(10, "m/s")). - Automatic Conversion: When writing to an OpenFOAM file,
OpenFOAMFile._format_valuechecks if the value is aQuantity. If so, it usesget_in(target_unit)to convert the value to the unit expected by OpenFOAM (defined inOpenFOAMFile.DEFAULT_UNITS), ensuring all written values are in OpenFOAM’s base units. - OpenFOAM Dimensions: The
to_openfoam_dimensions()method usespintto derive OpenFOAM’s dimension vector (M, L, T, Θ, N, J, A) from the unit, which is crucial for generating field file headers (e.g.,U,p).
4.3. Solver and Field Orchestration (Solver and CaseFieldsManager)
The Solver class delegates field management to the CaseFieldsManager class (foampilot/foampilot/src/foampilot/base/cases_variables.py).
- Solver Selection:
Solver(foampilot/foampilot/src/foampilot/solver/solver.py) uses boolean properties (e.g.,self.compressible,self.with_gravity,self.is_vof) to determine the simulation type. The internal_update_solver()method selects the appropriate OpenFOAM solver (e.g.,incompressibleFluid,compressibleVoF) and updates theBaseSolverinstance. - Field Management:
CaseFieldsManageruses these properties to dynamically generate the list of required physical fields (e.g.,U,p,k,epsilon,T).- If
self.with_gravityis true, the pressure field becomesp_rgh. - If a turbulence model is defined, associated fields (
k,epsilon,omega,nut) are added. - This field list is then used by
Boundaryto initialize boundary conditions for all required fields.
- If
4.4. Advanced Boundary Condition Management (Boundary)
The Boundary class (foampilot/foampilot/src/foampilot/boundaries/boundaries_dict.py) translates physical boundary conditions into OpenFOAM configurations.
- Centralized Configuration: Uses a configuration dictionary (
BOUNDARY_CONDITIONS_CONFIG) mapping physical condition types (e.g.,"velocityInlet") to required OpenFOAM configurations for each field (U, p, k, etc.) based on the selected turbulence model. - Wildcard Application:
apply_condition_with_wildcard(pattern, condition_type, **kwargs)applies a condition to all patches matching a regular expression (pattern). - Condition Resolution: For each field,
_resolve_field_configdetermines the final OpenFOAM configuration. For example, a wall condition selects betweennoSliporslipand applies appropriate wall functions (wallFunction) for turbulence fields using theWALL_FUNCTIONSdictionary. - File Generation:
write_boundary_conditions()iterates over all fields managed byCaseFieldsManagerand usesOpenFOAMFile.write_boundary_fileto generate boundary condition files in the0/directory.
5. Developer Workflow (Based on muffler.py)
This usage example illustrates a typical workflow for a developer using foampilot:
| Step | Description | Key Classes and Methods |
|---|---|---|
| 1. Initialization | Set working directory and initialize solver. | Solver(path), FluidMechanics |
| 2. Physical Configuration | Determine fluid properties and apply them to configuration files. | FluidMechanics.get_fluid_properties(), solver.constant.transportProperties.nu = ... |
| 3. Mesh | Define geometry and mesh (often via classy_blocks integration) and generate blockMeshDict. |
classy_blocks.Cylinder, cb.Mesh(), Meshing(path, mesher="blockMesh") |
| 4. Boundary Conditions | Initialize and apply boundary conditions to mesh-defined patches. | solver.boundary.initialize_boundary(), solver.boundary.apply_condition_with_wildcard() |
| 5. File Writing | Generate all OpenFOAM configuration files on disk. | solver.system.write(), solver.constant.write(), solver.boundary.write_boundary_conditions() |
| 6. Execution | Run the OpenFOAM simulation. | solver.run_simulation() |
| 7. Post-Processing | Analyze results, generate visualizations and reports. | FoamPostProcessing, ResidualsPost, latex_pdf.LatexDocument |
This workflow highlights how the different foampilot modules interact to provide a complete abstraction of the OpenFOAM simulation process. To contribute effectively, a developer must understand how each module class interacts with the central Solver object and how Python commands are translated into OpenFOAM dictionary syntax.