FEniCS / FEniCSx
Open-source computing platform for solving partial differential equations (PDEs) using the finite element method. Express variational problems in near-mathematical notation and let FEniCS generate optimised solver code automatically.
The FEniCS Workflow
FEniCS transforms the classical PDE problem into a variational (weak) form. For example, Poisson's equation:
Strong form:
Weak (variational) form — what you write in UFL:
FEniCS compiles this directly from your Python code into efficient C++ assembly kernels.
FEniCSx Component Stack
DOLFINx
Core solver & I/O
UFL
Variational form language
FFCx
Form compiler
Basix
Element definitions
Key Features
Automated Code Generation
FEniCS uses UFL (Unified Form Language) to express variational problems in near-mathematical notation. The FFC (FEniCS Form Compiler) then generates optimised C++ code automatically — no manual assembly of element stiffness matrices.
Python & C++ Interfaces
High-level Python interface (DOLFINx) for rapid prototyping. C++ backend for production-grade performance. Seamless interop with NumPy, SciPy, and PETSc.
Rich Element Library
Lagrange, Brezzi-Douglas-Marini (BDM), Raviart-Thomas (RT), Nédélec, Crouzeix-Raviart, and discontinuous Galerkin elements. Arbitrary polynomial order.
Parallel Computing
Built on PETSc for distributed-memory parallelism. Mesh partitioning via ParMETIS/SCOTCH. Scales to thousands of MPI ranks on HPC clusters.
Example: Poisson Equation
import dolfinx
from dolfinx import fem, mesh
from mpi4py import MPI
import ufl
# Create unit square mesh
domain = mesh.create_unit_square(MPI.COMM_WORLD, 32, 32)
V = fem.functionspace(domain, ("Lagrange", 1))
# Define boundary condition
u_bc = fem.Function(V)
u_bc.interpolate(lambda x: x[0] * 0.0)
boundary_dofs = fem.locate_dofs_geometrical(V, lambda x: (x[0] < 1e-10) | (x[0] > 1 - 1e-10))
bc = fem.dirichletbc(u_bc, boundary_dofs)
# Define variational problem
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
f = fem.Constant(domain, -6.0)
a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
L = f * v * ufl.dx
# Solve
problem = fem.petsc.LinearProblem(a, L, bcs=[bc])
uh = problem.solve()Resources: Visit fenicsproject.org for documentation and tutorials. VELSTROM-specific FEniCS workflows for geotechnical and hydrological PDEs are under development.