Python finite-difference and finite-volume CFD project for rebuilding canonical incompressible-flow solvers from first principles. The focus is on numerical schemes, pressure-velocity coupling, boundary conditions, validation against analytical solutions, and visualisation of flow fields.
Currently implemented:
- 1D linear advection with upwind, leapfrog, Lax-Friedrichs, and Lax-Wendroff finite-difference schemes
- 1D linear advection with an explicit upwind finite-volume method
- 2D linear advection, with finite-difference and explicit upwind finite-volume methods
- 1D nonlinear convection / inviscid Burgers with upwind, Lax-Friedrichs, Richtmyer, one-step and two-step Lax-Wendroff, MacCormack, and implicit Beam-Warming schemes, including conservative flux-form variants
- 1D nonlinear convection with an explicit finite-volume method
- 2D nonlinear convection, with finite-difference and finite-volume methods
- 1D and 2D diffusion, with finite-difference and finite-volume methods
- 1D and 2D Burgers equation, with finite-difference and finite-volume methods
- 2D Laplace equation, with finite-difference and finite-volume methods
- 2D Poisson equation with configurable source terms, with finite-difference and finite-volume methods
- 2D lid-driven cavity flow using a pressure Poisson solve, with finite-difference and finite-volume methods
- 2D pressure-driven channel flow with periodic x-boundaries, with finite-difference and finite-volume methods
- uniform grid generation for finite differences, and cell-centred mesh generation with face areas, cell volumes and centre-to-centre distances for finite volumes
- hat-function, Heaviside-style step, and Cole-Hopf initial conditions
- explicit finite-difference time-marching solvers
- iterative pressure/potential solves using L1 convergence or fixed iteration limits
- contour, surface, quiver, and animation visualizations
core/fdm/ finite-difference configs, grids, time steps, initial conditions, operators
core/fdm/solvers/ finite-difference solvers
core/fvm/ finite-volume configs, mesh, time steps, initial conditions, operators
core/fvm/solvers/ finite-volume solvers
core/analytical/ analytical reference solutions
data/ Ghia et al. (1982) reference tables
data/openfoam/ OpenFOAM case setups and extracted reference data
post_processing/ contour, surface, quiver, and animation helpers
runs/fdm/ finite-difference examples
runs/fvm/ finite-volume examples
runs/comparisons/fdm/ finite-difference validations
runs/comparisons/fvm/ finite-volume validations
runs/comparisons/fdm_vs_fvm/ finite-difference against finite-volume
tests/fdm/ finite-difference regression tests
tests/fvm/ finite-volume regression tests
The current solvers model:
-
the 1D linear advection equation:
du/dt + c du/dx = 0
using selectable explicit finite-difference schemes: upwind, leapfrog, Lax-Friedrichs, and Lax-Wendroff.
A finite-volume variant is also included, using an explicit upwind scheme on a cell-centered mesh with conservative flux updates and a CFL-based time-step constraint.
-
the 2D linear advection equation:
du/dt + c du/dx + c du/dy = 0
using an explicit upwind finite-difference scheme.
-
the 1D nonlinear convection equation:
du/dt + u du/dx = 0
and its conservative form:
du/dt + d(u^2 / 2)/dx = 0
using selectable explicit schemes: upwind, Lax-Friedrichs, Richtmyer, one-step Lax-Wendroff, two-step Lax-Wendroff, and MacCormack. Conservative flux-form variants are included for shock propagation, along with implicit Beam-Warming and damped implicit Beam-Warming variants for inviscid Burgers experiments.
A finite-volume variant is also included, using an explicit upwind scheme on a cell-centered mesh with conservative flux updates and a CFL-based time-step constraint.
-
the 2D nonlinear convection equations:
du/dt + u du/dx + v du/dy = 0
dv/dt + u dv/dx + v dv/dy = 0
using an explicit upwind finite-difference scheme.
-
the 1D diffusion equation:
du/dt = ν d²u/dx²
using an explicit central finite-difference scheme.
-
the 1D diffusion equation:
du/dt = nu d^2u/dx^2
using an explicit central finite-difference scheme. A 1D finite-volume diffusion variant is also included and can be compared against the heat-equation reference solution.
-
the 1D Burgers equation:
du/dt + u du/dx = nu d^2u/dx^2
with the conservative convective form:
du/dt + d(u^2 / 2)/dx = nu d^2u/dx^2
using an explicit upwind scheme for the finite-difference convective term and a central scheme for the diffusive term. A 1D finite-volume Burgers variant is also included, using conservative flux updates for the convective term and diffusive fluxes for viscosity, and can be compared against the Cole-Hopf analytical solution.
-
the 2D Burgers equations:
du/dt + u du/dx + v du/dy = ν (d²u/dx² + d²u/dy²)
dv/dt + u dv/dx + v dv/dy = ν (d²u/dx² + d²u/dy²)
using an explicit upwind scheme for the convective terms and a central scheme for the diffusive terms.
-
the 2D Laplace equation:
d²p/dx² + d²p/dy² = 0
solved iteratively with finite differences until an L1 target is reached.
-
the 2D Poisson equation:
d²p/dx² + d²p/dy² = b
solved iteratively with configurable positive and negative source terms.
-
the 2D incompressible lid-driven cavity flow problem:
du/dt + u du/dx + v du/dy = -1/rho dp/dx + nu (d^2u/dx^2 + d^2u/dy^2)
dv/dt + u dv/dx + v dv/dy = -1/rho dp/dy + nu (d^2v/dx^2 + d^2v/dy^2)
d^2p/dx^2 + d^2p/dy^2 = b
using explicit finite differences for the velocity equations and an iterative pressure Poisson solve. A finite-volume variant is also included, using conservative face fluxes for the convective terms, Green-Gauss gradients for the pressure, and a cell-centred pressure Poisson solve with zero-gradient walls and a Dirichlet lid.
-
the 2D incompressible pressure-driven channel flow problem:
du/dt + u du/dx + v du/dy = -1/rho dp/dx + nu (d^2u/dx^2 + d^2u/dy^2) + F
dv/dt + u dv/dx + v dv/dy = -1/rho dp/dy + nu (d^2v/dx^2 + d^2v/dy^2)
d^2p/dx^2 + d^2p/dy^2 = b
using explicit finite differences for the velocity equations, an iterative pressure Poisson solve, periodic boundary conditions in x, and no-slip walls at y = 0 and y = Ly. A finite-volume variant is also included, with wrap-around face fluxes on the periodic boundaries and the driving force applied to every cell.
This project includes validation workflows that compare numerical finite-difference solutions with analytical reference solutions.
For the 1D diffusion equation, finite-difference and finite-volume solvers can be compared against a Fourier-based analytical solution of the heat equation.
For the 1D Burgers equation, finite-difference and finite-volume solvers can be compared against the analytical Cole-Hopf solution.
The 1D convection scheme comparison script visualizes conservative and non-conservative schemes on a Heaviside step problem, comparing grid resolution and CFL number effects. This highlights numerical diffusion, dispersive oscillations near shocks, and conservative-form shock propagation.
The inviscid Burgers scheme comparison script studies conservative shock-capturing schemes, including implicit Beam-Warming and damped implicit Beam-Warming, across grid resolutions, CFL numbers, and artificial-damping coefficients.
These comparisons are used to assess solver correctness and visualize agreement between numerical and analytical results.
The 2D lid-driven cavity is validated against Ghia, Ghia and Shin (1982) at Re = 100, comparing u along the vertical centreline and v along the horizontal centreline against Tables I and II. The 2D channel flow is validated against the analytical Poiseuille profile.
Both solvers are also compared against OpenFOAM for the same two cases. The
case setups are in data/openfoam/ and the extracted reference data in
data/openfoam_*.csv.
The cavity case is a unit square on a 40 x 40 mesh, one cell thick with
empty front and back patches, solved with icoFoam. The lid is a
fixedValue of (1 0 0), the other three walls are noSlip, and the
kinematic viscosity is 0.01, giving Re = 100.
The channel case is a 2 x 1 domain on a 40 x 40 mesh, also one cell thick and
solved with the incompressibleFluid solver. The inlet and outlet are
cyclic, the top and bottom walls are noSlip, and the flow is driven by a
semiImplicitSource momentum source of (1 0 0) applied to all cells. The
kinematic viscosity is 0.1, matching the analytical peak velocity of 1.25.
Both cases run to t = 10 with a time step of 0.001.
| case | this solver | reference |
|---|---|---|
| Lid-driven cavity, Re=100, 40x40 | peak reverse u -0.217 | Ghia et al. -0.211 |
| Laminar channel, 40x40 | peak u 1.249 | analytical 1.250 |
| 2D Laplace and Poisson | 3e-9 | direct matrix solve |
| 1D advection at CFL 1 | machine precision | exact translation |
A regression suite of eighteen tests covers both packages, checking advection,
diffusion, Burgers, Laplace, Poisson, cavity and channel flow against these
references. Run it with pytest from the repository root.
- Add convergence studies for grid spacing and time-step sensitivity.
- Add limiters or artificial viscosity for oscillation control near shocks.
- Study damping sensitivity for implicit Beam-Warming schemes.
Install the package once, from the repository root:
pip install -e .Run the test suite:
pytestRun any example:
python runs/fdm/run_advection_1d.py
python runs/fdm/run_advection_2d.py
python runs/fdm/run_convection_1d.py
python runs/fdm/run_convection_2d.py
python runs/fdm/run_diffusion_1d.py
python runs/fdm/run_diffusion_2d.py
python runs/fdm/run_burgers_equation_1d.py
python runs/fdm/run_burgers_equation_2d.py
python runs/fdm/run_laplace_2d.py
python runs/fdm/run_poisson_2d.py
python runs/fdm/run_cavity_flow.py
python runs/fdm/run_channel_flow.py
python runs/fvm/run_advection_1d.py
python runs/fvm/run_advection_2d.py
python runs/fvm/run_convection_1d.py
python runs/fvm/run_convection_2d.py
python runs/fvm/run_diffusion_1d.py
python runs/fvm/run_diffusion_2d.py
python runs/fvm/run_burgers_equation_1d.py
python runs/fvm/run_burgers_equation_2d.py
python runs/fvm/run_laplace_2d.py
python runs/fvm/run_poisson_2d.py
python runs/fvm/run_cavity_flow.py
python runs/fvm/run_channel_flow.pyRun a scheme study or a validation:
python runs/comparisons/fdm/run_advection_1d_scheme_comparison.py
python runs/comparisons/fdm/run_convection_1d_scheme_comparison.py
python runs/comparisons/fdm/run_inviscid_burgers_scheme_comparison.py
python runs/comparisons/fdm/run_diffusion_1d_vs_heat.py
python runs/comparisons/fdm/run_burgers_equation_1d_vs_cole_hopf.py
python runs/comparisons/fdm/run_cavity_flow_vs_ghia.py
python runs/comparisons/fdm/run_cavity_flow_vs_openfoam.py
python runs/comparisons/fdm/run_cavity_flow_vs_ghia_vs_openfoam.py
python runs/comparisons/fdm/run_channel_flow_vs_analytical.py
python runs/comparisons/fdm/run_channel_flow_vs_openfoam.py
python runs/comparisons/fdm/run_channel_flow_vs_analytical_vs_openfoam.py
python runs/comparisons/fvm/run_diffusion_1d_vs_heat.py
python runs/comparisons/fvm/run_burgers_equation_1d_vs_cole_hopf.py
python runs/comparisons/fvm/run_cavity_flow_vs_ghia.py
python runs/comparisons/fvm/run_cavity_flow_vs_openfoam.py
python runs/comparisons/fvm/run_cavity_flow_vs_ghia_vs_openfoam.py
python runs/comparisons/fvm/run_channel_flow_vs_analytical.py
python runs/comparisons/fvm/run_channel_flow_vs_openfoam.py
python runs/comparisons/fvm/run_channel_flow_vs_analytical_vs_openfoam.py
python runs/comparisons/fdm_vs_fvm/run_cavity_flow.py
python runs/comparisons/fdm_vs_fvm/run_channel_flow.py














