scikit-fem is a lightweight Python 3.7+ library for performing finite element assembly. Its main purpose is the transformation of bilinear forms into sparse matrices and linear forms into vectors. The library supports triangular, quadrilateral, tetrahedral and hexahedral meshes as well as one-dimensional problems.

The library fills a gap in the spectrum of finite element codes. The library is lightweight and has minimal dependencies. It contains no compiled code meaning that it’s easy to install and use on all platforms that support NumPy. Despite being fully interpreted, the code has a reasonable performance.


The most recent release can be installed simply by

pip install scikit-fem


conda install -c conda-forge scikit-fem


Solve the Poisson problem (see also

from skfem import *
from skfem.helpers import dot, grad

# create the mesh
m = MeshTri().refined(4)
# or, with your own points and cells:
# m = MeshTri(points, cells)

e = ElementTriP1()
basis = InteriorBasis(m, e)

# this method could also be imported from skfem.models.laplace
def laplace(u, v, _):
    return dot(grad(u), grad(v))

# this method could also be imported from skfem.models.unit_load
def rhs(v, _):
    return 1.0 * v

A = asm(laplace, basis)
b = asm(rhs, basis)
# or:
# A = laplace.assemble(basis)
# b = rhs.assemble(basis)

# enforce Dirichlet boundary conditions
A, b = enforce(A, b, D=m.boundary_nodes())

# solve -- can be anything that takes a sparse matrix and a right-hand side
x = solve(A, b)

# plot the solution
from skfem.visuals.matplotlib import plot, savefig
plot(m, x, shading='gouraud', colorbar=True)


Meshes can be initialized manually, loaded from external files using

meshio, or created with the help of special


import numpy as np
from skfem import MeshLine, MeshTri, MeshTet

mesh = MeshLine(np.array([0., .5, 1.]))
mesh = MeshTri(
    np.array([[0., 0.],
              [1., 0.],
              [0., 1.]]).T,
    np.array([[0, 1, 2]]).T,
mesh = MeshTri.load("docs/examples/meshes/square.msh")
mesh = MeshTet.init_tensor(*((np.linspace(0, 1, 60),) * 3))

We support many common finite


Below the stiffness matrix is assembled using second-order tetrahedra:

from skfem import InteriorBasis, ElementTetP2

basis = InteriorBasis(mesh, ElementTetP2())  # quadratic tetrahedron
A = laplace.assemble(basis)  # type: scipy.sparse.csr_matrix

More examples can be found in the gallery.


The following benchmark (docs/examples/ demonstrates the time

spent on finite element assembly in comparison to the time spent on linear

solve. The given numbers were calculated using a ThinkPad X1 Carbon laptop (7th

gen). Note that the timings are only illustrative as they depend on, e.g., the

type of element used, the number of quadrature points used, the type of linear

solver, and the complexity of the forms. This benchmark solves the Laplace

equation using linear tetrahedral elements and the default direct sparse solver

of scipy.sparse.linalg.spsolve.

Degrees-of-freedomAssembly (s)Linear solve (s)