FEM Platform

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.

Python / C++
Finite Element Method
PETSc Backend
Open Source (LGPL)

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

poisson.py
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.