From-scratch finite element implementation with rigorous convergence verification
This repository implements P1 and P2 Lagrange finite element methods from scratch on unstructured triangular meshes, applied to three canonical PDE problems:
| Problem | Equation | Scheme |
|---|---|---|
| Poisson | P1 / P2 Galerkin | |
| Heat equation | P1 + Backward Euler | |
| Convection-diffusion | P1 + SUPG stabilization |
All implementations are verified against the theoretical a priori error estimates from Brenner & Scott, "The Mathematical Theory of Finite Element Methods" (Chapters 3–5).
| Method | Expected |
Observed |
Expected |
Observed |
|---|---|---|---|---|
| P1 Poisson | 1.998 | 0.999 | ||
| P2 Poisson | 3.000 | 1.997 | ||
| Heat (spatial) | 2.07 | 1.01 | ||
| Heat (temporal, BE) | 0.95 | — | — | |
| Condition number | 1.988 | — | — |
All observed rates match theory to within 1% on fine meshes.
Weak formulation: Find
Galerkin FEM: Replace
A priori error (Céa's Lemma + Aubin–Nitsche):
- P1: $|u - u_h|{H^1} \leq Ch,|u|{H^2}$, $\quad|u - u_h|{L^2} \leq Ch^2,|u|{H^2}$
- P2: $|u - u_h|{H^1} \leq Ch^2,|u|{H^3}$, $\quad|u - u_h|{L^2} \leq Ch^3,|u|{H^3}$
Fully discrete (Backward Euler + P1 FEM):
The system matrix
A priori error (Thomée, 2006):
Standard Galerkin becomes unstable when the mesh Péclet number
For P1 FEM on quasi-uniform meshes (Brenner & Scott, Thm 5.8.3):
This governs solver choice: direct solvers suffice for moderate
fem-solver-suite/
│
├── mesh/
│ └── mesh_generator.py — Structured triangular mesh on [0,1]²
│
├── fem/
│ ├── p1_elements.py — P1 local stiffness, mass, load (exact formula)
│ ├── p2_elements.py — P2 local stiffness, mass (6-pt Gauss quadrature)
│ ├── assembly.py — Sparse global assembly (COO → CSR)
│ └── solvers.py — Direct (spsolve) + CG-ILU + condition number
│
├── problems/
│ ├── poisson.py — P1/P2 convergence study, manufactured solutions
│ ├── heat_equation.py — Backward Euler + spatial/temporal convergence
│ └── conv_diffusion.py — SUPG assembly + Péclet number study
│
├── analysis/
│ ├── error_norms.py — L² and H¹ error by 6-pt Gaussian quadrature
│ └── condition_number.py — κ(K) vs h study
│
├── results/ — Generated figures (PDF + PNG)
│
├── run_all.py — Master script: reproduces all experiments
├── make_summary_figure.py — Generates the 2×3 summary plot
└── README.md
git clone https://github.com/akhilesh-yadav/fem-solver-suite.git
cd fem-solver-suite
pip install numpy scipy matplotlibNo FEniCS or external FEM library required. Everything is implemented from scratch.
# Run all experiments and generate all figures
python run_all.py
# Generate combined summary figure
python make_summary_figure.pyExpected runtime: ~2–3 minutes on a standard laptop.
P1 (linear, 3 DOFs/element):
Basis functions = barycentric coordinates
Local stiffness matrix (exact formula, no quadrature needed for constant gradients):
P2 (quadratic, 6 DOFs/element): 3 vertex nodes + 3 edge midpoint nodes. Assembled using 6-point Gauss quadrature on the reference triangle (exact for degree-4 integrands).
Dirichlet BCs are enforced by row/column elimination with symmetric modification:
for each boundary DOF
| Problem size | Solver used |
|---|---|
scipy.sparse.linalg.spsolve (direct, sparse LU) |
|
| Conjugate Gradient + ILU(0) preconditioner | |
| Time-dependent | LU factorized once, back-substitution at each step |
All convergence studies use the Method of Manufactured Solutions (MMS):
choose
| Problem | Exact solution | Why chosen |
|---|---|---|
| Smooth Poisson | Satisfies homogeneous Dirichlet BC exactly; smooth | |
| Polynomial | In |
|
| High-frequency | Tests resolution on coarse meshes | |
| Heat equation | Homogeneous heat; |
-
P2 is dramatically more accurate than P1 at the same DOF count: P2 at
$n=8$ achieves$L^2$ error$4.57 \times 10^{-4}$ ; P1 needs$n=32$ to reach similar accuracy ($1.35 \times 10^{-3}$ ). -
Condition number scales exactly as
$h^{-2}$ : fitted slope 1.988 vs theoretical 2.0. For$n=64$ ($h=1/64$ ),$\kappa \approx 1660$ , manageable with direct solvers. At$n=256$ ,$\kappa \approx 26{,}000$ — preconditioning becomes essential. -
SUPG prevents spurious oscillations for
$Pe > 1$ : at$\varepsilon = 0.001$ ($Pe \approx 17$ ), standard Galerkin gives$L^2$ error$6.9 \times 10^{-4}$ while SUPG gives$8.4 \times 10^{-4}$ (SUPG slightly larger due to added artificial diffusion, but far more stable in$L^\infty$ ). -
Backward Euler temporal rate converges to 1.0: observed rate 0.95–1.01, confirming the
$O(\Delta t)$ estimate from Thomée.
- S.C. Brenner & L.R. Scott — The Mathematical Theory of Finite Element Methods (3rd ed.)
- L.C. Evans — Partial Differential Equations, AMS
- V. Thomée — Galerkin Finite Element Methods for Parabolic Problems
- A.N. Brooks & T.J.R. Hughes — SUPG formulations for convective dominated flows, CMAME 1982
- A. Ern & J.-L. Guermond — Theory and Practice of Finite Elements, Springer
Akhilesh Yadav | akhileshyadav.maths@gmail.com
GitHub: github.com/akhilesh-yadav
