Goals & core concepts

This section explains the why behind NeoFOAM’s design. Read these pages to build a mental model of how src/neofoam/solver/incompressibleFluid/ is wired. For step-by-step recipes see Install NeoFOAM; for guided lessons see the tutorials listed in Welcome to NeoFOAM!.

The core abstraction

A NeoFOAM solver is a sequence of custom operations that act on a shared Context. The solver author declares the loop topology and contributes some operations; plugin models contribute more; the framework merges them into one ordered DAG and runs them against a Context object that holds fields, models, the mesh, and the runtime.

That is the whole library, in one sentence. Everything else exists to make it work.

        flowchart LR
    OP1["Operation A<br/>(solver)"]
    OP2["Operation B<br/>(plugin)"]
    OP3["Operation C<br/>(solver)"]
    OP4["Operation D<br/>(plugin)"]
    CTX[("Context<br/>fields · models<br/>mesh · runtime")]

    OP1 -->|reads/writes| CTX
    CTX --> OP2
    OP2 -->|reads/writes| CTX
    CTX --> OP3
    OP3 -->|reads/writes| CTX
    CTX --> OP4
    OP4 -->|reads/writes| CTX

    style CTX fill:#FFF3E0
    style OP1 fill:#E3F2FD
    style OP2 fill:#FCE4EC
    style OP3 fill:#E3F2FD
    style OP4 fill:#FCE4EC
    

The four goals

  1. Multi-physics code — run multiple coupled physics (turbulence + transport + optional models like Boussinesq) inside one solver, without solver-side edits per combination.

  2. Simplify usability — typed configs, IDE autocomplete, validation before solve, JSON schema for external tooling.

  3. Extensibility — third-party packages contribute physics models, schemes, and operations as plugins, without forking the solver.

  4. Integration of other numerical methods — alternate numerical backends (NeoN GPU kernels, Ginkgo solvers) plug in behind a typed interface.

The core feature that delivers the goals

The DAG-resolved operation graph (see Operations and the DAG) is what carries every goal:

  • Solver and plugin operations are merged and topologically sorted into one loop — that is multi-physics code without solver edits.

  • The merger places third-party operations in the right scope based on declared depends_on / before constraints — that is extensibility.

  • The Pydantic configs that operations depend on are typed, validated, and schema-exported — that is simplify usability.

  • The compute called inside operations runs through pybFoam / NeoN — that is integration of other numerical methods.

Read Operations and the DAG first if you want one page that shows the core in action.