API Reference

Note

Auto-generated API documentation requires pybFoam and OpenFOAM to be installed. If sections below are empty, build the docs in an environment with OpenFOAM sourced.

postprocessor

PostProcessor classes for decorator-based output registration.

This module provides the PostProcessorInterface protocol, PostProcessorBase, and PostProcessorRunner classes for the simplified API with decorator-based output registration and extensible writer components.

class pyOFTools.postprocessor.PostProcessorBase(base_path: str = 'postProcessing/')

Base class for post-processor with decorator-based output registration.

This class provides a decorator API for registering post-processing functions that will be called during simulation runtime. Output writers are selected automatically based on file extension.

Args:

base_path: Base directory for output files (default: “postProcessing/”)

Example:
>>> postProcess = PostProcessorBase()
>>>
>>> @postProcess.Table("mass.csv")
... def total_mass(mesh):
...     return field(mesh, "rho") | VolIntegrate()
>>>
>>> # In OpenFOAM function object:
>>> processor = postProcess(mesh)
>>> processor.execute()  # Called each time step
>>> processor.write()    # Called when writing output
>>> processor.end()      # Called at end of simulation
Table(filename: str, **kwargs: Any) Callable[[...], Any]

Decorator to register a function as a table output.

Uses TableWriter which dispatches to format-specific writers (CSV, HDF5, etc.) based on file extension.

Args:

filename: Output filename (extension determines format) **kwargs: Additional arguments passed to the writer (e.g., writeControl, writeInterval)

Returns:

Decorator function

Example:
>>> @postProcess.Table("results.csv", writeControl="timeStep", writeInterval=10)
... def compute_result(mesh):
...     return field(mesh, "p") | VolIntegrate()
class pyOFTools.postprocessor.PostProcessorInterface(*args, **kwargs)

Protocol for post-processor output writers.

This protocol defines the interface that all output writers must implement to be compatible with the PostProcessorBase registry system.

Output writers are selected automatically based on file extension and must implement the OpenFOAM function object interface: execute(), write(), end().

end() bool

End method called at simulation end.

Returns:

True to indicate success

execute() bool

Execute method called each time step.

Returns:

True to indicate success

write() bool

Write method called when output should be written.

Returns:

True to indicate success

class pyOFTools.postprocessor.PostProcessorRunner(mesh: fvMesh, outputs: dict[str, tuple[Callable[..., Any], type[PostProcessorInterface], dict[str, Any]]], base_path: str)

Post-processor runner instance for executing registered outputs.

This class implements the OpenFOAM function object interface (execute, write, end) and manages polymorphic output writers via the PostProcessorInterface protocol.

Args:

mesh: OpenFOAM mesh object outputs: Dictionary of registered output configurations (func, writer_cls, kwargs) base_path: Base directory for output files

end() bool

End method called at simulation end.

Delegates to all registered output writers for cleanup.

Returns:

True to indicate success

execute() bool

Execute method called each time step.

Delegates to all registered output writers.

Returns:

True to indicate success

write() bool

Write method called when output should be written.

Delegates to all registered output writers.

Returns:

True to indicate success

builders

Builders for simplified post-processing workflows.

This module provides high-level functions for creating workflows from OpenFOAM fields, surfaces, and lines.

Geometry builders:
  • field(mesh, name) — volume field

  • iso_surface(mesh, iso_field, iso_value) — iso-surface (geometry only)

  • plane(mesh, point, normal) — cutting plane (geometry only)

  • line(mesh, name, start, end, n, field_name) — line sample

Field selection nodes (used with |):
  • area() — face area magnitudes from surface geometry

  • sample(mesh, field_name) — interpolate a volume field onto a surface

Example:

iso_surface(mesh, "alpha.water", 0.5) | area() | Sum()
iso_surface(mesh, "alpha.water", 0.5) | sample(mesh, "p") | Mean()
plane(mesh, point=(0.5,0,0), normal=(1,0,0)) | sample(mesh, "T") | Max()
field(mesh, "p") | VolIntegrate()
line(mesh, "centreline", (0,0,0), (1,0,0), 100, "p") | Mean()
pyOFTools.builders.area() Area

Face area magnitudes from surface geometry.

Use in a pipe after a surface builder:

iso_surface(mesh, "alpha.water", 0.5) | area() | Sum()
pyOFTools.builders.field(mesh: fvMesh, name: str) Any

Create a WorkFlow from a registered volScalarField.

Args:

mesh: OpenFOAM mesh object name: Name of the field in the object registry

Example:

field(mesh, "alpha.water") | VolIntegrate()
pyOFTools.builders.iso_surface(mesh: fvMesh, iso_field: str, iso_value: float) Any

Create a WorkFlow for an iso-surface (geometry only, no field).

Pipe into area() or sample() to select what to compute:

iso_surface(mesh, "alpha.water", 0.5) | area() | Sum()
iso_surface(mesh, "alpha.water", 0.5) | sample(mesh, "p") | Mean()
Args:

mesh: OpenFOAM mesh object iso_field: Name of the scalar field to create iso-surface from iso_value: Value for the iso-surface

pyOFTools.builders.line(mesh: fvMesh, name: str, start: Tuple[float, float, float] | List[float], end: Tuple[float, float, float] | List[float], n_points: int, field_name: str, scheme: str = 'cellPoint') Any

Create a WorkFlow from a uniform line sample.

Args:

mesh: OpenFOAM mesh object name: Name for the sampled set start: Start point (x, y, z) end: End point (x, y, z) n_points: Number of sample points field_name: Name of the volume field to sample scheme: Interpolation scheme (default: “cellPoint”)

Example:

line(mesh, "centreline", (0,0,0), (1,0,0), 100, "p") | Mean()
pyOFTools.builders.plane(mesh: fvMesh, point: Tuple[float, float, float] = (0.0, 0.0, 0.0), normal: Tuple[float, float, float] = (1.0, 0.0, 0.0)) Any

Create a WorkFlow for a cutting plane (geometry only, no field).

Pipe into area() or sample() to select what to compute:

plane(mesh, point=(0.5,0,0), normal=(1,0,0)) | sample(mesh, "T") | Max()
Args:

mesh: OpenFOAM mesh object point: Point on the plane (x, y, z) normal: Normal vector (nx, ny, nz)

pyOFTools.builders.residuals(mesh: fvMesh) Any

Create a WorkFlow for solver residuals.

Args:

mesh: OpenFOAM mesh object

Example:

residuals(mesh)
pyOFTools.builders.sample(mesh: fvMesh, field_name: str, scheme: str = 'cellPoint') Sample

Interpolate a volume field onto a surface.

Use in a pipe after a surface builder:

iso_surface(mesh, "alpha.water", 0.5) | sample(mesh, "p") | Mean()
Args:

mesh: OpenFOAM mesh object field_name: Name of the volume field to sample scheme: Interpolation scheme (default: “cellPoint”)

aggregators

class pyOFTools.aggregators.Max(*, type: Literal['max'] = 'max', name: str | None = None)
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet) AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
type: Literal['max']
class pyOFTools.aggregators.Mean(*, type: Literal['mean'] = 'mean', name: str | None = None)
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet) AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
type: Literal['mean']
class pyOFTools.aggregators.Min(*, type: Literal['min'] = 'min', name: str | None = None)
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet) AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
type: Literal['min']
class pyOFTools.aggregators.Sum(*, type: Literal['sum'] = 'sum', name: str | None = None)
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet) AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
type: Literal['sum']
class pyOFTools.aggregators.SurfIntegrate(*, type: Literal['surfIntegrate'] = 'surfIntegrate', name: str | None = None)
compute(dataset: SurfaceDataSet) AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
type: Literal['surfIntegrate']
class pyOFTools.aggregators.VolIntegrate(*, type: Literal['volIntegrate'] = 'volIntegrate', name: str | None = None)
compute(dataset: InternalDataSet) AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
type: Literal['volIntegrate']

binning

class pyOFTools.binning.Directional(*, type: Literal['directional'] = 'directional', bins: list[float], direction: Tuple[float, float, float], origin: Tuple[float, float, float] = (0.0, 0.0, 0.0))
bins: list[float]
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
direction: Tuple[float, float, float]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

origin: Tuple[float, float, float]
type: Literal['directional']

spatial_selectors

class pyOFTools.spatial_selectors.BinarySpatialSelector(*, type: Literal['binary'], op: Literal['and', 'or'], left: Box | Sphere | NotSpatialSelector | BinarySpatialSelector, right: Box | Sphere | NotSpatialSelector | BinarySpatialSelector)
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
left: SpatialSelectorModel
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

op: Literal['and', 'or']
right: SpatialSelectorModel
type: Literal['binary']
class pyOFTools.spatial_selectors.Box(*, type: Literal['box'] = 'box', min: Tuple[float, float, float], max: Tuple[float, float, float])
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
max: Tuple[float, float, float]
min: Tuple[float, float, float]
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

type: Literal['box']
class pyOFTools.spatial_selectors.NotSpatialSelector(*, type: Literal['not'], region: Box | Sphere | NotSpatialSelector | BinarySpatialSelector)
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

region: SpatialSelectorModel
type: Literal['not']
class pyOFTools.spatial_selectors.SpatialSelector(*, type: str = 'node')
compute(coords: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class pyOFTools.spatial_selectors.Sphere(*, type: Literal['sphere'] = 'sphere', center: Tuple[float, float, float], radius: float)
center: Tuple[float, float, float]
compute(dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

radius: float
type: Literal['sphere']

workflow

class pyOFTools.workflow.WorkFlow(*, initial_dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet, steps: list[~typing.Annotated[~pyOFTools.aggregators.Sum | ~pyOFTools.aggregators.VolIntegrate | ~pyOFTools.aggregators.SurfIntegrate | ~pyOFTools.aggregators.Mean | ~pyOFTools.aggregators.Max | ~pyOFTools.aggregators.Min | ~pyOFTools.builders.Area | ~pyOFTools.builders.Sample, FieldInfo(annotation=NoneType, required=True, discriminator='type')]] = <factory>)
compute() InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
initial_dataset: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

steps: list[Annotated[Sum | VolIntegrate | SurfIntegrate | Mean | Max | Min | Area | Sample, FieldInfo(annotation=NoneType, required=True, discriminator='type')]]
then(step: Annotated[Sum | VolIntegrate | SurfIntegrate | Mean | Max | Min | Area | Sample, FieldInfo(annotation=NoneType, required=True, discriminator='type')]) WorkFlow
pyOFTools.workflow.create_workflow() Any

Build the WorkFlow model class.

node

class pyOFTools.node.Node(*, type: str = 'node')
classmethod build_discriminated_union() Any
compute(dataset: DataSets) DataSets
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod register() Any
registry: ClassVar[list[type]] = [<class 'pyOFTools.aggregators.Sum'>, <class 'pyOFTools.aggregators.VolIntegrate'>, <class 'pyOFTools.aggregators.SurfIntegrate'>, <class 'pyOFTools.aggregators.Mean'>, <class 'pyOFTools.aggregators.Max'>, <class 'pyOFTools.aggregators.Min'>, <class 'pyOFTools.builders.Area'>, <class 'pyOFTools.builders.Sample'>, <class 'pyOFTools.binning.Directional'>, <class 'pyOFTools.spatial_selectors.Box'>, <class 'pyOFTools.spatial_selectors.Sphere'>, <class 'pyOFTools.spatial_selectors.NotSpatialSelector'>, <class 'pyOFTools.spatial_selectors.BinarySpatialSelector'>, <class '__main__.Variance'>]
type: str

datasets

class pyOFTools.datasets.AggregatedData(*, value: float | int | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vector, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dd90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensor, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9de10>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensor, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ded0>], group: list[int | str] | None = None, group_name: list[str] | None = None)
group: list[int | str] | None
group_name: list[str] | None
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

value: SimpleType
class pyOFTools.datasets.AggregatedDataSet(*, name: str, values: list[AggregatedData])
property grouped_values: list[list[float | int | str]]
property headers: list[str]
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
values: list[AggregatedData]
class pyOFTools.datasets.InternalDataSet(*, name: str, field: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.scalarField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vectorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce50>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d390>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d890>], geometry: ~pyOFTools.geometry.InternalMesh, mask: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.boolList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dc10>] | None = None, groups: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.labelList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dcd0>] | None = None)
field: FieldType
geometry: InternalMesh
groups: PydanticLabelList | None
mask: PydanticBoolList | None
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class pyOFTools.datasets.PatchDataSet(*, name: str, field: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.scalarField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vectorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce50>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d390>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d890>], geometry: ~pyOFTools.geometry.BoundaryMesh, mask: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.boolList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dc10>] | None = None, groups: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.labelList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dcd0>] | None = None)
field: FieldType
geometry: BoundaryMesh
groups: PydanticLabelList | None
mask: PydanticBoolList | None
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class pyOFTools.datasets.PointDataSet(*, name: str, field: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.scalarField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vectorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce50>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d390>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d890>], geometry: ~pyOFTools.geometry.SetGeometry, mask: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.boolList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dc10>] | None = None, groups: ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.labelList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dcd0>] | None = None)
field: FieldType
geometry: SetGeometry
groups: PydanticLabelList | None
mask: PydanticBoolList | None
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class pyOFTools.datasets.SurfaceDataSet(*, name: str, field: scalarField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vectorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce50>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d390>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d890>] | None=None, geometry: SurfaceMesh, mask: boolList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dc10>] | None=None, groups: labelList, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9dcd0>] | None=None)
field: FieldType | None
geometry: SurfaceMesh
groups: PydanticLabelList | None
mask: PydanticBoolList | None
model_config = {'arbitrary_types_allowed': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str

surfaces

Convenience utilities for creating common surface types.

This module provides factory functions for easily creating different types of sampled surfaces without dealing with OpenFOAM dictionary setup directly.

pyOFTools.surfaces.create_cutting_plane(mesh: fvMesh, name: str, point: Tuple[float, float, float], normal: Tuple[float, float, float], interpolate: bool = True) sampledSurface

Create a cutting plane surface using the cuttingPlane algorithm.

Similar to sampledPlane but uses a different algorithm that may produce better results in some cases.

Args:

mesh: OpenFOAM mesh name: Name for the surface point: Point on the plane (x, y, z) normal: Normal vector (nx, ny, nz) interpolate: Whether to interpolate values (default: True)

Returns:

sampledCuttingPlane surface instance

Example:
>>> from pyOFTools.surfaces import create_cutting_plane
>>>
>>> # Create a horizontal plane at z=0.1
>>> surface = create_cutting_plane(
...     mesh,
...     "horizontal",
...     point=(0, 0, 0.1),
...     normal=(0, 0, 1)
... )
pyOFTools.surfaces.create_iso_surface(name: str, mesh: fvMesh, field: scalarField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vectorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce50>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d390>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d890>] | None, iso_field_name: str, iso_value: float) SurfaceDataSet

Create an iso-surface of a scalar field.

An iso-surface is the 3D equivalent of a contour line, representing all points where a field has a specific value.

Args:

name: Name for the surface mesh: OpenFOAM mesh field: Field to sample on the surface iso_field_name: Name of the scalar field to create iso-surface from iso_value: Value for the iso-surface interpolate: Whether to interpolate values (default: True) regularise: Whether to regularise the surface (default: True)

Returns:

SurfaceDataSet containing the isoSurface

Example:
>>> from pyOFTools.surfaces import create_iso_surface
>>>
>>> # Create iso-surface where alpha.water = 0.5 (interface)
>>> interface = create_iso_surface(
...     "interface",
...     mesh,
...     field=alpha_field,
...     iso_field_name="alpha.water",
...     iso_value=0.5
... )
pyOFTools.surfaces.create_patch_surface(mesh: fvMesh, name: str, patches: List[str], triangulate: bool = False) sampledSurface

Create a surface from one or more mesh boundary patches.

This is useful for sampling fields on boundary surfaces, such as walls, inlets, or outlets.

Args:

mesh: OpenFOAM mesh name: Name for the surface patches: List of patch names to include in the surface triangulate: Whether to triangulate the surface (default: False)

Returns:

sampledPatch surface instance

Example:
>>> from pyOFTools.surfaces import create_patch_surface
>>>
>>> # Sample on all wall boundaries
>>> wall_surface = create_patch_surface(
...     mesh,
...     "walls",
...     patches=["leftWall", "rightWall", "bottomWall"]
... )
pyOFTools.surfaces.create_plane(name: str, mesh: fvMesh, field: scalarField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce90>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.vectorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9ce50>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.tensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d390>] | ~pybFoam.pybFoam_core.Annotated[~pybFoam.pybFoam_core.symmTensorField, <pyOFTools.datasets._PydanticWrapper object at 0x7f46dab9d890>] | None=None, point: Tuple[float, float, float]=(0.0, 0.0, 0.0), normal: Tuple[float, float, float]=(1.0, 0.0, 0.0), triangulate: bool = False, mask: boolList | None = None, groups: labelList | None = None) SurfaceDataSet

sets

Convenience utilities for creating common sampledSet types.

This module provides factory functions for easily creating different types of sampled sets (lines, curves, point clouds) without dealing with OpenFOAM dictionary setup directly.

pyOFTools.sets.create_circle_set(mesh: fvMesh, name: str, origin: Tuple[float, float, float], circle_axis: Tuple[float, float, float], start_point: Tuple[float, float, float], d_theta: float, field: volScalarField | volVectorField | volTensorField | volSymmTensorField, axis: str = 'distance', scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint') PointDataSet

Create a circle sampledSet with interpolated field values.

Creates a circular sampling path. The circle is defined by its center (origin), normal direction (circle_axis), and a starting point on the circumference.

Args:

mesh: OpenFOAM mesh name: Name for the set origin: Center point of circle (x, y, z) circle_axis: Normal vector of circle plane (nx, ny, nz) start_point: Starting point on circle circumference (defines radius) d_theta: Angular increment in degrees (default: 10.0) field: Volume field to interpolate axis: Output axis type (usually “distance”) scheme: Interpolation scheme (default: “cellPoint”)

Returns:

PointDataSet containing interpolated field values and geometry

Example:
>>> from pyOFTools.sets import create_circle_set
>>>
>>> # Create horizontal circle at z=0.5 with radius 0.3
>>> circle = create_circle_set(
...     mesh,
...     "circle",
...     origin=(0.5, 0.5, 0.5),
...     circle_axis=(0.0, 0.0, 1.0),  # Normal to xy-plane
...     start_point=(0.8, 0.5, 0.5),  # Radius = 0.3
...     d_theta=5.0,
...     field=p
... )
pyOFTools.sets.create_cloud_set(mesh: fvMesh, name: str, points: List[Tuple[float, float, float]], field: volScalarField | volVectorField | volTensorField | volSymmTensorField, axis: str = 'xyz', scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint') PointDataSet

Create a cloud (arbitrary points) sampledSet with interpolated field values.

Creates a set of sample points at arbitrary user-specified locations. Useful for validation against experimental probe locations or specific points of interest.

Args:

mesh: OpenFOAM mesh name: Name for the set points: List of sample point coordinates [(x,y,z), …] field: Volume field to interpolate axis: Output axis type (usually “xyz” for clouds) scheme: Interpolation scheme (default: “cellPoint”)

Returns:

PointDataSet containing interpolated field values and geometry

Example:
>>> from pyOFTools.sets import create_cloud_set
>>>
>>> # Sample at specific probe locations
>>> probes = create_cloud_set(
...     mesh,
...     "probes",
...     points=[
...         (0.1, 0.2, 0.3),
...         (0.5, 0.5, 0.5),
...         (0.8, 0.7, 0.6)
...     ]
... )
pyOFTools.sets.create_polyline_set(mesh: fvMesh, name: str, points: List[Tuple[float, float, float]], n_points: int, field: volScalarField | volVectorField | volTensorField | volSymmTensorField, axis: str = 'distance', scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint') PointDataSet

Create a polyLine (multi-segment) sampledSet with interpolated field values.

Creates a path through multiple knot points with sample points distributed along all segments. Useful for sampling along curved paths or through complex geometry.

Args:

mesh: OpenFOAM mesh name: Name for the set points: List of knot points defining the polyline path n_points: Total number of sample points (distributed across all segments) field: Volume field to interpolate axis: Output axis type (usually “distance”) scheme: Interpolation scheme (default: “cellPoint”)

Returns:

PointDataSet containing interpolated field values and geometry

Example:
>>> from pyOFTools.sets import create_polyline_set
>>>
>>> # Create L-shaped path
>>> path = create_polyline_set(
...     mesh,
...     "Lpath",
...     points=[
...         (0.0, 0.0, 0.5),  # Start
...         (1.0, 0.0, 0.5),  # Corner
...         (1.0, 1.0, 0.5)   # End
...     ],
...     n_points=100
... )
pyOFTools.sets.create_uniform_set(mesh: fvMesh, name: str, start: Tuple[float, float, float] | List[float], end: Tuple[float, float, float] | List[float], n_points: int, field: volScalarField | volVectorField | volTensorField | volSymmTensorField, axis: str = 'distance', scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint') PointDataSet

Create a uniform (straight line) sampledSet with interpolated field values.

Creates a straight line with uniformly distributed sample points between start and end positions, and interpolates the provided field onto those points.

Args:

mesh: OpenFOAM mesh name: Name for the set start: Start point (x, y, z) end: End point (x, y, z) n_points: Number of sample points field: Volume field to interpolate (volScalarField, volVectorField, etc.) axis: Output axis type: “distance” (default), “x”, “y”, “z”, or “xyz”. scheme: Interpolation scheme (default: “cellPoint”)

Returns:

PointDataSet containing interpolated field values and geometry

Example:
>>> from pybFoam import fvMesh, Time, volScalarField
>>> from pyOFTools.sets import create_uniform_set
>>>
>>> time = Time(".", ".")
>>> mesh = fvMesh(time)
>>> p = volScalarField.read_field(mesh, "p")
>>>
>>> # Create horizontal line with pressure values
>>> dataset = create_uniform_set(
...     mesh,
...     "centerline",
...     start=(0.0, 0.5, 0.5),
...     end=(1.0, 0.5, 0.5),
...     n_points=100,
...     field=p
... )
>>>
>>> # Access interpolated values and geometry
>>> positions = dataset.geometry.positions
>>> pressures = dataset.field
>>> distances = dataset.geometry.distance

interpolation

Surface field interpolation utilities.

This module provides tools for interpolating volume fields onto surfaces, separating interpolation logic from geometry to allow flexible sampling strategies.

class pyOFTools.interpolation.SurfaceInterpolator(scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint', use_point_data: bool = False)

Handles interpolation of volume fields onto surfaces.

This class separates the interpolation logic from surface geometry, allowing the same surface to be used with different fields and interpolation schemes without rebuilding the surface.

Attributes:

scheme: OpenFOAM interpolation scheme name use_point_data: Whether to interpolate to surface points (True) or face centers (False)

Example:
>>> from pybFoam import fvMesh, Time, volScalarField
>>> from pybFoam.sampling import sampledPlane
>>> from pyOFTools.interpolation import SurfaceInterpolator
>>>
>>> # Setup mesh and surface
>>> time = Time(".", ".")
>>> mesh = fvMesh(time)
>>> surface = create_plane_surface(mesh, "plane", (0.5, 0, 0), (1, 0, 0))
>>>
>>> # Create interpolator
>>> interpolator = SurfaceInterpolator(scheme="cellPoint", use_point_data=False)
>>>
>>> # Interpolate field
>>> field = volScalarField.from_registry(mesh, "p")
>>> interpolated_values = interpolator.interpolate(field, surface)
interpolate(field: volScalarField | volVectorField | volTensorField | volSymmTensorField, surface: sampledSurface) scalarField | vectorField | tensorField | symmTensorField

Interpolate a volume field onto a surface.

Args:

field: OpenFOAM volume field to interpolate surface: sampledSurface to interpolate onto

Returns:

Interpolated field values on the surface (on faces or points depending on use_point_data)

Raises:

TypeError: If field type is not supported

pyOFTools.interpolation.create_interpolated_dataset(field: VolFieldType, surface: sampling.sampledSurface, interpolator: SurfaceInterpolator, name: str | None = None) SurfaceDataSet

Convenience function to create a SurfaceDataSet with interpolated values.

This function combines surface geometry and field interpolation into a single dataset object that can be used with the pyOFTools workflow system.

Args:

field: Volume field to interpolate surface: Surface to interpolate onto interpolator: Interpolator instance to use name: Name for the dataset (defaults to field name)

Returns:

SurfaceDataSet with interpolated field values and geometry

Example:
>>> from pyOFTools.interpolation import create_interpolated_dataset, SurfaceInterpolator
>>> from pyOFTools.surfaces import create_plane_surface
>>>
>>> # Create surface and interpolator
>>> surface = create_plane_surface(mesh, "plane", (0.5, 0, 0), (1, 0, 0))
>>> interpolator = SurfaceInterpolator(scheme="cellPoint")
>>>
>>> # Create dataset
>>> field = volScalarField.from_registry(mesh, "alpha.water")
>>> dataset = create_interpolated_dataset(field, surface, interpolator, name="alpha")
>>>
>>> # Use in workflow
>>> from pyOFTools.workflow import WorkFlow
>>> from pyOFTools.aggregators import Sum
>>> workflow = WorkFlow(initial_dataset=dataset).then(Sum())
>>> result = workflow.execute()

set_interpolation

Set field interpolation utilities.

This module provides tools for interpolating volume fields onto sampledSets (lines, curves, point clouds), separating interpolation logic from geometry to allow flexible sampling strategies.

class pyOFTools.set_interpolation.SetInterpolator(scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint')

Handles interpolation of volume fields onto sampledSets.

This class separates the interpolation logic from set geometry, allowing the same set to be used with different fields and interpolation schemes without rebuilding the set.

Attributes:

scheme: OpenFOAM interpolation scheme name

Example:
>>> from pybFoam import fvMesh, Time, volScalarField
>>> from pybFoam.sampling import sampledSet
>>> from pyOFTools.set_interpolation import SetInterpolator
>>> from pyOFTools.sets import create_uniform_set
>>>
>>> # Setup mesh and set
>>> time = Time(".", ".")
>>> mesh = fvMesh(time)
>>> line = create_uniform_set(mesh, "line", (0,0,0), (1,0,0), 50)
>>>
>>> # Create interpolator
>>> interpolator = SetInterpolator(scheme="cellPoint")
>>>
>>> # Interpolate field
>>> field = volScalarField.read_field(mesh, "p")
>>> interpolated_values = interpolator.interpolate(field, line)
interpolate(field: volScalarField | volVectorField | volTensorField | volSymmTensorField, sampled_set: sampledSet) scalarField | vectorField | tensorField | symmTensorField

Interpolate a volume field onto a sampledSet.

Args:

field: OpenFOAM volume field to interpolate sampled_set: sampledSet to interpolate onto

Returns:

Interpolated field values at sample points

Raises:

TypeError: If field type is not supported

pyOFTools.set_interpolation.create_set_dataset(sampled_set: sampledSet, field: volScalarField | volVectorField | volTensorField | volSymmTensorField, name: str, scheme: Literal['cell', 'cellPoint', 'cellPointFace'] = 'cellPoint', mask_invalid: bool = True) PointDataSet

Create a PointDataSet from a sampledSet and field.

Convenience function that combines set geometry wrapping, field interpolation, and dataset creation into a single call.

Args:

sampled_set: OpenFOAM sampledSet instance field: Volume field to interpolate name: Name for the dataset scheme: Interpolation scheme (default: “cellPoint”) mask_invalid: If True, create a mask for invalid points (default: True)

Returns:

PointDataSet containing interpolated field values and geometry

Example:
>>> from pybFoam import Time, fvMesh, volScalarField
>>> from pyOFTools.sets import create_uniform_set
>>> from pyOFTools.set_interpolation import create_set_dataset
>>>
>>> time = Time(".", ".")
>>> mesh = fvMesh(time)
>>>
>>> # Create line
>>> line = create_uniform_set(mesh, "line", (0,0,0), (1,0,0), 50)
>>>
>>> # Read field
>>> p = volScalarField.read_field(mesh, "p")
>>>
>>> # Create dataset in one step
>>> dataset = create_set_dataset(line, p, "pressure_line")
>>>
>>> # Access data
>>> positions = dataset.geometry.positions
>>> values = dataset.field

geometry

class pyOFTools.geometry.BoundaryMesh(*args, **kwargs)
property positions: vectorField
class pyOFTools.geometry.FvMeshInternalAdapter(mesh: fvMesh)
property positions: vectorField
property volumes: scalarField
class pyOFTools.geometry.InternalMesh(*args, **kwargs)
property positions: vectorField
property volumes: scalarField
class pyOFTools.geometry.SampledSetAdapter(sampled_set: sampledSet)

Adapter for OpenFOAM sampledSet to provide SetGeometry protocol.

This adapter wraps a pybFoam.sampling.sampledSet instance and provides a convenient interface for accessing set geometry information (points and distance).

Example:
>>> from pybFoam import fvMesh, Time
>>> from pybFoam.sampling import meshSearch, sampledSet, UniformSetConfig
>>> from pyOFTools.geometry import SampledSetAdapter
>>>
>>> time = Time(".", ".")
>>> mesh = fvMesh(time)
>>> search = meshSearch(mesh)
>>>
>>> # Create a line sampledSet
>>> config = UniformSetConfig(
...     axis="distance",
...     start=[0, 0, 0],
...     end=[1, 0, 0],
...     nPoints=50
... )
>>> set_dict = config.to_foam_dict()
>>> line = sampledSet.New("myLine", mesh, search, set_dict)
>>>
>>> # Wrap in adapter
>>> adapter = SampledSetAdapter(line)
>>>
>>> # Access geometry
>>> positions = adapter.positions  # vectorField of sample points
>>> distances = adapter.distance   # scalarField of cumulative distances
property distance: scalarField

Return cumulative distance along the set.

property positions: vectorField

Return sample point positions.

class pyOFTools.geometry.SampledSurfaceAdapter(surface: sampledSurface)

Adapter for OpenFOAM sampledSurface to provide SurfaceMesh protocol.

This adapter wraps a pybFoam.sampling.sampledSurface instance and provides a convenient interface for accessing surface geometry information.

Example:
>>> from pybFoam import sampling, fvMesh, Time, dictionary, word, vector
>>> from pyOFTools.geometry import SampledSurfaceAdapter
>>>
>>> time = Time(".", ".")
>>> mesh = fvMesh(time)
>>>
>>> # Create a plane surface
>>> plane_dict = dictionary()
>>> plane_dict.set("type", word("plane"))
>>> plane_dict.set("basePoint", vector(0.5, 0, 0))
>>> plane_dict.set("normalVector", vector(1, 0, 0))
>>>
>>> surface = sampling.sampledPlane(word("myPlane"), mesh, plane_dict)
>>> adapter = SampledSurfaceAdapter(surface)
>>>
>>> # Access geometry
>>> face_centers = adapter.positions
>>> area = adapter.total_area
property face_area_magnitudes: scalarField

Return face area magnitudes.

property face_areas: vectorField

Return face area vectors.

property face_centers: vectorField

Return face center positions (same as positions).

property name: str

Return the name of the surface.

property points: vectorField

Return surface points (vertices).

property positions: vectorField

Return face center positions of the surface.

property total_area: float

Return total surface area.

update() bool

Update surface if needed.

Returns:

True if surface was updated, False otherwise.

class pyOFTools.geometry.SetGeometry(*args, **kwargs)

Protocol for sampled set geometry.

Represents the geometric information of a sampledSet: an ordered collection of sample points (along lines, curves, or clouds) with a distance metric. Not a mesh in the connectivity sense, but a geometric point collection.

property distance: scalarField

Cumulative distance along the set (or arbitrary metric for clouds).

property positions: vectorField

Sample point positions in 3D space.

class pyOFTools.geometry.SurfaceMesh(*args, **kwargs)

Protocol for surface meshes with geometry information.

property face_area_magnitudes: scalarField

Face area magnitudes.

property face_areas: vectorField

Face area vectors.

property positions: vectorField

Face center positions of the surface.

property total_area: float

Total surface area.

residuals

Extract solver performance information from OpenFOAM solverPerformanceDict.

pyOFTools.residuals.residual_dataset(mesh: fvMesh, time_value: float | None = None) AggregatedDataSet

Extract solver performance information from mesh including inner iterations.

Args:

mesh: OpenFOAM mesh object time_value: Optional time value (unused, kept for API consistency)

Returns:

AggregatedDataSet with solver performance for all fields in long format. Each inner iteration gets its own row with iteration index.

Example:
>>> mesh = pf.fvMesh(time)
>>> perf_data = residual_dataset(mesh)
>>> # Headers: ['solverPerformance', 'field', 'solver', 'metric', 'iteration']

tables

Output writers for post-processing.

This package contains implementations of the PostProcessorInterface protocol for various output formats (CSV, VTK, HDF5, etc.).

class pyOFTools.tables.TableWriter(mesh: fvMesh, func: Callable[[fvMesh], Any], base_path: str, filename: str, writeControl: str = 'writeTime', writeInterval: int = 1)

Table writer with format dispatch implementing PostProcessorInterface.

This writer dispatches to format-specific writers (CSV, DAT, etc.) based on file extension using Pydantic discriminated unions. It implements the OpenFOAM function object interface (execute, write, end) and handles write control logic.

Args:

mesh: OpenFOAM mesh object func: Workflow function to evaluate base_path: Base directory for output files filename: Output filename (extension determines format) writeControl: When to write (“writeTime” or “timeStep”) writeInterval: Interval for writing (default: 1)

Example:
>>> def compute_mass(mesh):
...     return field(mesh, "rho") | VolIntegrate()
>>> writer = TableWriter(
...     mesh=mesh,
...     func=compute_mass,
...     base_path="postProcessing/",
...     filename="results.csv",
...     writeControl="timeStep",
...     writeInterval=10
... )
>>> writer.execute()
>>> writer.write()
>>> writer.end()
end() bool

End method called at simulation end.

Closes the format writer.

Returns:

True to indicate success

execute() bool

Execute method called each time step.

Increments internal step counter for write control.

Returns:

True to indicate success

write() bool

Write method called when output should be written.

Evaluates the workflow function and writes results if write control conditions are met.

Returns:

True to indicate success

TableWriter for table output with format dispatch.

This module provides a TableWriter class that implements the PostProcessorInterface protocol for writing workflow results to various table formats (CSV, DAT, etc.) using Pydantic discriminated unions for format selection.

class pyOFTools.tables.table.CSVFormatConfig(*, format: Literal['csv'] = 'csv', file_path: str)

Configuration for CSV format writer.

create_writer() CSVWriter

Create a CSVWriter instance.

file_path: str
format: Literal['csv']
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class pyOFTools.tables.table.DATFormatConfig(*, format: Literal['dat'] = 'dat', file_path: str)

Configuration for DAT format writer (alias for CSV).

create_writer() CSVWriter

Create a CSVWriter instance (DAT uses CSV format).

file_path: str
format: Literal['dat']
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class pyOFTools.tables.table.TableWriter(mesh: fvMesh, func: Callable[[fvMesh], Any], base_path: str, filename: str, writeControl: str = 'writeTime', writeInterval: int = 1)

Table writer with format dispatch implementing PostProcessorInterface.

This writer dispatches to format-specific writers (CSV, DAT, etc.) based on file extension using Pydantic discriminated unions. It implements the OpenFOAM function object interface (execute, write, end) and handles write control logic.

Args:

mesh: OpenFOAM mesh object func: Workflow function to evaluate base_path: Base directory for output files filename: Output filename (extension determines format) writeControl: When to write (“writeTime” or “timeStep”) writeInterval: Interval for writing (default: 1)

Example:
>>> def compute_mass(mesh):
...     return field(mesh, "rho") | VolIntegrate()
>>> writer = TableWriter(
...     mesh=mesh,
...     func=compute_mass,
...     base_path="postProcessing/",
...     filename="results.csv",
...     writeControl="timeStep",
...     writeInterval=10
... )
>>> writer.execute()
>>> writer.write()
>>> writer.end()
end() bool

End method called at simulation end.

Closes the format writer.

Returns:

True to indicate success

execute() bool

Execute method called each time step.

Increments internal step counter for write control.

Returns:

True to indicate success

write() bool

Write method called when output should be written.

Evaluates the workflow function and writes results if write control conditions are met.

Returns:

True to indicate success

class pyOFTools.tables.csvWriter.CSVWriter(*, file_path: str, header: list[str] | None = None)
close() None
create_file() None
file_path: str
header: list[str] | None
model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

write_result(time: float, result: InternalDataSet | PatchDataSet | SurfaceDataSet | PointDataSet | AggregatedDataSet) None

Write pre-computed result to CSV (no workflow.compute() call).