Home

Awesome

scikit-fem

scikit-fem is a pure Python 3.8+ library for performing finite element assembly. Its main purpose is the transformation of bilinear forms into sparse matrices and linear forms into vectors.

<a href="https://colab.research.google.com/github/kinnala/scikit-fem-notebooks/blob/master/ex1.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg"></a> <a href="https://scikit-fem.readthedocs.io/" alt="Documentation"><img src="https://readthedocs.org/projects/pip/badge/?version=stable" /></a> <a href="https://joss.theoj.org/papers/4120aba1525403e6d0972f4270d7b61e" alt="status"><img src="https://joss.theoj.org/papers/4120aba1525403e6d0972f4270d7b61e/status.svg" /></a> <a href="https://pypi.org/project/scikit-fem/" alt="PyPI"><img src="https://img.shields.io/pypi/v/scikit-fem" /></a>

The library

If you use the library in your research, you can cite the following article:

@article{skfem2020,
  doi = {10.21105/joss.02369},
  year = {2020},
  volume = {5},
  number = {52},
  pages = {2369},
  author = {Tom Gustafsson and G. D. McBain},
  title = {scikit-fem: A {P}ython package for finite element assembly},
  journal = {Journal of Open Source Software}
}

Installation

The most recent release can be installed simply by

pip install scikit-fem[all]

Remove [all] to not install the optional dependencies meshio for mesh input/output, and matplotlib for creating simple visualizations. The minimal dependencies are numpy and scipy. You can also try the library in browser through Google Colab.

Examples

Solve the Poisson problem (see also ex01.py):

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

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

basis = Basis(mesh, ElementTriP1())

@BilinearForm
def laplace(u, v, _):
    return dot(grad(u), grad(v))

@LinearForm
def rhs(v, _):
    return 1. * v

A = laplace.assemble(basis)
b = rhs.assemble(basis)

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

# solve the linear system
x = solve(A, b)

# plot using matplotlib
mesh.plot(x, shading='gouraud', colorbar=True).show()
# or, save to external file:
# mesh.save('output.vtk', point_data={'solution': x})

Meshes can be initialized manually, loaded from external files using meshio, or created with the help of special constructors:

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")  # requires meshio
mesh = MeshTet.init_tensor(*((np.linspace(0, 1, 60),) * 3))

We support many common finite elements. Below the stiffness matrix is assembled using second-order tetrahedra:

from skfem import Basis, ElementTetP2

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

More examples can be found in the gallery.

Benchmark

The following benchmark (docs/examples/performance.py) 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)
40960.048050.04241
80000.098040.16269
156250.203470.87741
327680.463995.98163
640001.0014336.47855
1250002.05274nan
2621444.48825nan
5120008.82814nan
103030118.25461nan

Documentation

The project is documented using Sphinx under docs/. Built version can be found from Read the Docs. Here are direct links to additional resources:

Getting help

If you encounter an issue you can use GitHub issue tracker. If you cannot find help from the documentation, you can use the GitHub Discussions to ask questions. Try to provide a snippet of code which fails and include also the version of the library you are using. The version can be found as follows:

import skfem; print(skfem.__version__)

Dependencies

The minimal dependencies for installing scikit-fem are numpy and scipy. In addition, many examples use matplotlib for visualization and meshio for loading/saving different mesh file formats. Some examples demonstrate the use of other external packages; see requirements.txt for a list of test dependencies.

Testing

The tests are run by GitHub Actions. The Makefile in the repository root has targets for running the testing container locally using docker. For example, make test_py38 runs the tests using py38 branch from kinnala/scikit-fem-docker-action. The releases are tested in kinnala/scikit-fem-release-tests.

Licensing

The contents of skfem/ and the PyPI package scikit-fem are licensed under the 3-clause BSD license. Some examples under docs/examples/ or snippets in the documentation may have a different license.

Acknowledgements

This project was started while working under a grant from the Finnish Cultural Foundation. Versions 2.0.0+ were prepared while working in a project funded by Academy of Finland (decisions nr. 324611 and 338341). The approach used in the finite element assembly has been inspired by the work of A. Hannukainen and M. Juntunen.

Contributing

We are happy to welcome any contributions to the library. Reasonable projects for first timers include:

By contributing code to scikit-fem, you are agreeing to release it under BSD-3-Clause, see LICENSE.md.

Changelog

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning with respect to documented and/or tested features.

[10.0.2] - 2024-09-03

[10.0.1] - 2024-08-06

[10.0.0] - 2024-07-25

[9.1.1] - 2024-04-23

[9.0.1] - 2024-01-12

[9.0.0] - 2023-12-24

[8.1.0] - 2023-06-16

[8.0.0] - 2022-12-16

[7.0.1] - 2022-08-03

[7.0.0] - 2022-08-03

[6.0.0] - 2022-03-15

[5.2.0] - 2021-12-27

[5.1.0] - 2021-11-30

[5.0.0] - 2021-11-21

[4.0.1] - 2021-10-15

[4.0.0] - 2021-09-27

[3.2.0] - 2021-08-02

[3.1.0] - 2021-06-18

[3.0.0] - 2021-04-19

[2.5.0] - 2021-02-13

[2.4.0] - 2021-01-20

[2.3.0] - 2020-11-24

[2.2.3] - 2020-10-16

[2.2.2] - 2020-10-15

[2.2.1] - 2020-10-15

[2.2.0] - 2020-10-14

[2.1.1] - 2020-10-01

[2.1.0] - 2020-09-30

[2.0.0] - 2020-08-21

[1.2.0] - 2020-07-07

[1.1.0] - 2020-05-18

[1.0.0] - 2020-04-22