FiPy is a finite volume partial differential equation (PDE) solver written in Python and designed to let researchers and engineers express models in a way that closely follows the underlying physics. Many users start by running examples or adapting snippets, but real productivity comes from understanding how FiPy is structured internally and how its major components interact. Once you have a clear mental model of FiPy’s architecture, debugging becomes easier, models scale more naturally, and performance decisions make more sense.
This article explains FiPy’s core architecture from the ground up. Instead of focusing on heavy mathematics, it focuses on how FiPy organizes geometry, data, equations, and solvers, and how these pieces fit together during a simulation.
The mental model of FiPy in one flow
At a high level, FiPy follows a consistent pipeline:
- define a mesh that represents the geometry,
- define variables that live on that mesh,
- build equation terms that represent physical processes,
- assemble those terms into equations,
- solve the resulting system using a numerical solver,
- advance in time and visualize or export results.
Every FiPy script, from the simplest diffusion example to complex multiphysics models, follows this same structure. Understanding each layer individually makes the whole framework feel predictable rather than magical.
The mesh layer
What a mesh represents in FiPy
In FiPy, the mesh represents the spatial discretization of the physical domain. It consists of cells (control volumes) and faces (interfaces between cells). Finite volume methods work by enforcing conservation laws over each cell, so cell volumes and face areas are fundamental quantities.
Each cell stores information about its volume and location, while each face stores geometric information such as area and normal direction. These geometric properties are used internally when FiPy computes fluxes across faces.
Common mesh types
Most users start with uniform structured meshes in one, two, or three dimensions. These are easy to reason about and fast to compute. The same concepts apply regardless of dimension: a two-dimensional mesh behaves the same way as a three-dimensional mesh from the solver’s point of view.
The important distinction to keep in mind is not the dimension, but where quantities live: some values are associated with cells, while others are associated with faces.
Mesh data you use without realizing it
Many FiPy operations rely on mesh attributes behind the scenes. Cell volumes, face areas, face normals, and connectivity information are all pulled from the mesh when equations are assembled. You rarely need to compute these manually, but understanding that they exist explains why FiPy naturally conserves mass, energy, or other quantities.
The variables layer
Cell variables and face variables
Variables represent physical fields. A cell variable stores one value per cell and is commonly used for quantities like temperature, concentration, or phase-field order parameters. A face variable stores one value per face and is often used for fluxes or face-centered coefficients.
This distinction is central to FiPy’s architecture. Many new users struggle when a coefficient is placed on cells when it should be on faces, or vice versa. When in doubt, ask whether the quantity represents something averaged over a volume or something defined on an interface.
Boundary conditions as constraints
Boundary conditions in FiPy are implemented as constraints on variables. A fixed-value boundary condition constrains the value of a variable at selected faces, while flux-type conditions influence how terms contribute to the equation assembly.
Because boundary conditions are attached to variables rather than hard-coded into solvers, they integrate cleanly with the equation-building process. This design keeps equations modular and easier to modify.
Old and new values in time-dependent problems
For transient problems, FiPy tracks both current and previous values of variables. This allows time discretization schemes to compare old and new states when assembling transient terms. Explicit and implicit time integration both rely on this mechanism.
The terms layer
Why FiPy uses terms
Terms are the building blocks of equations in FiPy. Each term represents a physical contribution, such as diffusion, convection, a source, or a transient component. Instead of writing one large monolithic equation, you compose an equation by adding terms together.
This modular approach makes equations readable and flexible. Adding or removing physics often means adding or removing a term, rather than rewriting the entire model.
Common terms you will encounter
A transient term represents time dependence. Diffusion terms represent gradients driving fluxes. Convection terms represent transport by a velocity field. Source terms represent local generation or consumption. Each term knows how to discretize itself on the mesh.
Implicit and explicit behavior
Terms can be treated implicitly or explicitly. Implicit terms contribute to the system matrix and generally improve stability, especially for stiff problems. Explicit terms contribute only to the right-hand side and often require smaller time steps for stability.
Choosing which terms are implicit is one of the most important architectural decisions in a FiPy model. Poor choices often manifest as unstable simulations or extremely small time steps.
Equation assembly
From symbolic expression to linear system
When you combine terms into an equation, FiPy assembles a linear system internally. Each term contributes entries to a matrix and a right-hand-side vector based on the mesh geometry, variable values, and coefficients.
Users rarely interact directly with these matrices, but understanding that they exist explains why solver choice and conditioning matter so much.
Coupled equations
Many real problems involve multiple variables governed by coupled equations. FiPy supports this by allowing systems of equations to be solved together. Coupled solves are more expensive but necessary when variables strongly depend on each other.
Nonlinear problems
Nonlinearities arise when coefficients depend on the solution itself. FiPy handles this through iterative solution strategies, where equations are reassembled and solved repeatedly until convergence criteria are met.
The solver layer
Linear solvers and iteration
Solvers operate on the assembled linear system. They compute updates to the variable values that reduce the residual. For nonlinear problems, linear solves occur inside an outer iteration loop.
Solver performance depends on problem size, matrix structure, and parameter choices. While defaults often work for small problems, large simulations require more careful tuning.
Diagnostics and convergence
Residual norms, iteration counts, and convergence behavior provide critical feedback. If a solver stagnates or diverges, it often indicates issues with boundary conditions, discretization choices, or time-step size.
Time stepping and simulation control
The typical time loop
Most FiPy simulations use an explicit time loop. At each step, equations are solved, variables are updated, and results may be visualized or saved. The time-step size controls both stability and accuracy.
Stopping criteria
A simulation may stop after a fixed physical time or when a steady state is reached. Detecting steady state often involves monitoring changes in variables or integrated quantities.
Visualization, export, and reproducibility
Interactive viewers
Viewers provide immediate feedback during development. They help catch errors early, such as incorrect boundary conditions or unstable discretizations. Viewer issues in headless environments are common and do not indicate numerical failure.
Exporting results
For serious analysis, results should be written to files along with metadata describing the mesh, parameters, and solver settings. This supports reproducibility and postprocessing.
Common architectural mistakes
Confusing cell-based and face-based quantities
Many bugs arise from placing coefficients on the wrong geometric entities. Always verify whether a quantity represents a volume-averaged value or a flux across faces.
Overusing explicit terms
Excessive explicit treatment often forces very small time steps. Moving stiff physics into implicit terms usually improves stability and efficiency.
Ignoring diagnostics
A simulation that runs is not necessarily correct. Monitoring residuals, conserved quantities, and convergence behavior is essential.
FiPy architecture cheat sheet
| Component | Role | User controls | Common pitfalls |
|---|---|---|---|
| Mesh | Geometry and topology | Resolution, dimension | Poor resolution, wrong dimension |
| Variables | Physical fields | Initial values, constraints | Cell vs face confusion |
| Terms | Physical processes | Implicit or explicit form | Instability from poor choices |
| Equations | System assembly | Coupling structure | Overly complex coupling |
| Solvers | Numerical solution | Tolerances, iterations | Divergence or slow convergence |
When FiPy’s architecture is a good fit
FiPy excels at rapid prototyping of PDE models, research simulations, and educational use. Its architecture favors clarity and modularity over extreme specialization. Problems requiring exotic geometries or highly specialized solvers may require different tools, but for many transport and phase-field problems, FiPy’s structure is a strong match.
Conclusion
FiPy’s architecture can be summarized simply: a mesh defines geometry, variables store physical fields, terms represent physics, equations assemble systems, solvers compute updates, and time loops advance the solution. Once this mental model is clear, FiPy becomes easier to reason about, easier to debug, and more powerful as a research tool.