{"id":13699303,"url":"https://github.com/maroba/findiff","last_synced_at":"2025-10-18T19:51:03.681Z","repository":{"id":37580068,"uuid":"125622959","full_name":"maroba/findiff","owner":"maroba","description":"Python package for numerical derivatives and partial differential equations in any number of dimensions.","archived":false,"fork":false,"pushed_at":"2025-01-05T15:50:08.000Z","size":2463,"stargazers_count":475,"open_issues_count":7,"forks_count":64,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-12T22:14:40.230Z","etag":null,"topics":["derivative","finite-difference","finite-difference-coefficients","finite-differences","numerical-methods","partial-differential-equations","pde","scientific-computing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maroba.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["maroba"]}},"created_at":"2018-03-17T11:34:40.000Z","updated_at":"2025-05-07T14:25:35.000Z","dependencies_parsed_at":"2024-11-20T22:24:47.586Z","dependency_job_id":"bb9eeafc-effd-4be2-8082-57d542c600ad","html_url":"https://github.com/maroba/findiff","commit_stats":{"total_commits":423,"total_committers":11,"mean_commits":38.45454545454545,"dds":"0.13475177304964536","last_synced_commit":"b0258bcb09fbc6e2c1877b9a78abcacfcdfb884c"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Ffindiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Ffindiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Ffindiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maroba%2Ffindiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maroba","download_url":"https://codeload.github.com/maroba/findiff/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254168127,"owners_count":22026091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["derivative","finite-difference","finite-difference-coefficients","finite-differences","numerical-methods","partial-differential-equations","pde","scientific-computing"],"created_at":"2024-08-02T20:00:30.129Z","updated_at":"2025-10-18T19:50:58.629Z","avatar_url":"https://github.com/maroba.png","language":"Python","funding_links":["https://github.com/sponsors/maroba"],"categories":["\u003cspan id=\"head11\"\u003e3.1. Differentiation, Quadrature and Tensor computation\u003c/span\u003e"],"sub_categories":["\u003cspan id=\"head12\"\u003e3.1.1. Auto Differentiation\u003c/span\u003e"],"readme":"# \u003cimg src=\"docs/frontpage/findiff_logo.png\" width=\"100px\"\u003e findiff\n\n[![PyPI version](https://badge.fury.io/py/findiff.svg)](https://img.shields.io/pypi/v/findiff.png?style=flat-square\u0026color=brightgreen)\n![build](https://github.com/maroba/findiff/actions/workflows/check.yml/badge.svg)\n![Coverage](https://img.shields.io/codecov/c/github/maroba/findiff/master.svg)\n[![Doc Status](https://readthedocs.org/projects/findiff/badge/?version=latest)](https://findiff.readthedocs.io/en/latest/index.html)\n[![PyPI downloads](https://img.shields.io/pypi/dm/findiff.svg)]()\n[![Downloads](https://static.pepy.tech/personalized-badge/findiff?period=total\u0026units=international_system\u0026left_color=black\u0026right_color=blue\u0026left_text=Downloads)](https://pepy.tech/project/findiff)\n\nA Python package for finite difference numerical derivatives and partial differential equations in\nany number of dimensions.\n\n## Main Features\n\n* Differentiate arrays of any number of dimensions along any axis with any desired accuracy order\n* Accurate treatment of grid boundary\n* Can handle arbitrary linear combinations of derivatives with constant and variable coefficients\n* Fully vectorized for speed\n* Matrix representations of arbitrary linear differential operators\n* Solve partial differential equations with Dirichlet or Neumann boundary conditions\n* Symbolic representation of finite difference schemes\n* **New in version 0.11**: More comfortable API (keeping the old API available)\n* **New in version 0.12**: Periodic boundary conditions for differential operators and PDEs.\n\n## Installation\n\n```\npip install --upgrade findiff\n```\n\n## Documentation and Examples\n\nYou can find the documentation of the code including examples of application at https://findiff.readthedocs.io/en/stable/.\n\n## Taking Derivatives\n\n*findiff* allows to easily define derivative operators that you can apply to *numpy* arrays of \nany dimension. \n\nConsider the simple 1D case of a equidistant grid\nwith a first derivative $\\displaystyle \\frac{\\partial}{\\partial x}$ along the only axis (0):\n\n```python\nimport numpy as np\nfrom findiff import Diff\n\n# define the grid:\nx = np.linspace(0, 1, 100)\n\n# the array to differentiate:\nf = np.sin(x)  # as an example\n\n# Define the derivative:\nd_dx = Diff(0, x[1] - x[0])\n\n# Apply it:\ndf_dx = d_dx(f) \n```\n\nSimilarly, you can define partial derivatives along other axes, for example, if $z$ is the 2-axis, we can write\n$\\frac{\\partial}{\\partial z}$ as:\n\n```python\nDiff(2, dz)\n```\n\n`Diff` always creates a first derivative. For higher derivatives, you simply exponentiate them, for example for $\\frac{\\partial^2}{\\partial_x^2}$\n\n```\nd2_dx2 = Diff(0, dx)**2\n```\n\nand apply it as before.\n\nYou can also define more general differential operators intuitively, like\n\n$$\n2x \\frac{\\partial^3}{\\partial x^2 \\partial z} + 3 \\sin(y)z^2 \\frac{\\partial^3}{\\partial x \\partial y^2}\n$$\n\n\nwhich can be written as\n\n```python\n# define the operator\ndiff_op = 2 * X * Diff(0)**2 * Diff(2) + 3 * sin(Y) * Z**2 * Diff(0) * Diff(1)**2\n\n# set the grid you use (equidistant here)\ndiff_op.set_grid({0: dx, 1: dy, 2: dz})\n\n# apply the operator\nresult = diff_op(f)\n```\n\nwhere `X, Y, Z` are *numpy* arrays with meshed grid points. Here you see that you can also define your grid\nlazily.\n\nOf course, standard operators from vector calculus like gradient, divergence and curl are also available\nas shortcuts.\n\nIf one or more axis of your grid are periodic, you can specify that when defining the derivative or later\nwhen setting the grid. For example:\n\n```python\nd_dx = Diff(0, dx, periodic=True)\n\n# or later\nd_dx = Diff(0)\nd_dx.set_grid({0: {\"h\": dx, \"periodic\": True}})\n```\n\nMore examples can be found [here](https://findiff.readthedocs.io/en/latest/source/examples.html) and in [this blog](https://medium.com/p/7e54132a73a3).\n\n### Accuracy Control\n\nWhen constructing an instance of `Diff`, you can request the desired accuracy\norder by setting the keyword argument `acc`. For example:\n\n```python\nd_dx = Diff(0, dy, acc=4)\ndf_dx = d2_dx2(f)\n```\n\nAlternatively, you can also split operator definition and configuration:\n\n```python\nd_dx = Diff(0, dx)\nd_dx.set_accuracy(2)\ndf_dx = d2_dx2(f)\n```\n\nwhich comes in handy if you have a complicated expression of differential operators, because then you\ncan specify it on the whole expression and it will be passed down to all basic operators.\n\nIf not specified, second order accuracy will be taken by default.\n\n## Finite Difference Coefficients\n\nSometimes you may want to have the raw finite difference coefficients.\nThese can be obtained for __any__ derivative and accuracy order\nusing `findiff.coefficients(deriv, acc)`. For instance,\n\n```python\nimport findiff\ncoefs = findiff.coefficients(deriv=3, acc=4, symbolic=True)\n```\n\ngives\n\n```\n{'backward': {'coefficients': [15/8, -13, 307/8, -62, 461/8, -29, 49/8],\n              'offsets': [-6, -5, -4, -3, -2, -1, 0]},\n 'center': {'coefficients': [1/8, -1, 13/8, 0, -13/8, 1, -1/8],\n            'offsets': [-3, -2, -1, 0, 1, 2, 3]},\n 'forward': {'coefficients': [-49/8, 29, -461/8, 62, -307/8, 13, -15/8],\n             'offsets': [0, 1, 2, 3, 4, 5, 6]}}\n```\n\nIf you want to specify the detailed offsets instead of the\naccuracy order, you can do this by setting the offset keyword\nargument:\n\n```python\nimport findiff\ncoefs = findiff.coefficients(deriv=2, offsets=[-2, 1, 0, 2, 3, 4, 7], symbolic=True)\n```\n\nThe resulting accuracy order is computed and part of the output:\n\n```\n{'coefficients': [187/1620, -122/27, 9/7, 103/20, -13/5, 31/54, -19/2835], \n 'offsets': [-2, 1, 0, 2, 3, 4, 7], \n 'accuracy': 5}\n```\n\n## Matrix Representation\n\nFor a given differential operator, you can get the matrix representation\nusing the `matrix(shape)` method, e.g. for a small 1D grid of 10 points:\n\n```python\nd2_dx2 = Diff(0, dx)**2\nmat = d2_dx2.matrix((10,))  # this method returns a scipy sparse matrix\nprint(mat.toarray())\n```\n\nhas the output\n\n```\n[[ 2. -5.  4. -1.  0.  0.  0.]\n [ 1. -2.  1.  0.  0.  0.  0.]\n [ 0.  1. -2.  1.  0.  0.  0.]\n [ 0.  0.  1. -2.  1.  0.  0.]\n [ 0.  0.  0.  1. -2.  1.  0.]\n [ 0.  0.  0.  0.  1. -2.  1.]\n [ 0.  0.  0. -1.  4. -5.  2.]]\n```\n\nIf you have periodic boundary conditions, the matrix looks like that:\n\n```python\nd2_dx2 = Diff(0, dx, periodic=True)**2\nmat = d2_dx2.matrix((10,))  # this method returns a scipy sparse matrix\nprint(mat.toarray())\n```\n\n```\n[[-2.  1.  0.  0.  0.  0.  1.]\n [ 1. -2.  1.  0.  0.  0.  0.]\n [ 0.  1. -2.  1.  0.  0.  0.]\n [ 0.  0.  1. -2.  1.  0.  0.]\n [ 0.  0.  0.  1. -2.  1.  0.]\n [ 0.  0.  0.  0.  1. -2.  1.]\n [ 1.  0.  0.  0.  0.  1. -2.]]\n```\n\n## Stencils\n\n*findiff* uses standard stencils (patterns of grid points) to evaluate the derivative.\nHowever, you can design your own stencil. A picture says more than a thousand words, so\nlook at the following example for a standard second order accurate stencil for the\n2D Laplacian $\\displaystyle \\frac{\\partial^2}{\\partial x^2} + \\frac{\\partial^2}{\\partial y^2}$:\n\n\u003cimg src=\"docs/frontpage/laplace2d.png\" width=\"400\"\u003e\n\nThis can be reproduced by *findiff* writing\n\n```python\noffsets = [(0, 0), (1, 0), (-1, 0), (0, 1), (0, -1)]\nstencil = Stencil(offsets, partials={(2, 0): 1, (0, 2): 1}, spacings=(1, 1))\n```\n\nThe attribute `stencil.values` contains the coefficients\n\n```\n{(0, 0): -4.0, (1, 0): 1.0, (-1, 0): 1.0, (0, 1): 1.0, (0, -1): 1.0}\n```\n\nNow for a some more exotic stencil. Consider this one:\n\n\u003cimg src=\"docs/frontpage/laplace2d-x.png\" width=\"400\"\u003e\n\nWith *findiff* you can get it easily:\n\n```python\noffsets = [(0, 0), (1, 1), (-1, -1), (1, -1), (-1, 1)]\nstencil = Stencil(offsets, partials={(2, 0): 1, (0, 2): 1}, spacings=(1, 1))\nstencil.values\n```\n\nwhich returns\n\n```\n{(0, 0): -2.0, (1, 1): 0.5, (-1, -1): 0.5, (1, -1): 0.5, (-1, 1): 0.5}\n```\n\n## Symbolic Representations\n\nAs of version 0.10, findiff can also provide a symbolic representation of finite difference schemes suitable for using in conjunction with sympy. The main use case is to facilitate deriving your own iteration schemes.\n\n```python\nfrom findiff import SymbolicMesh, SymbolicDiff\n\nmesh = SymbolicMesh(\"x, y\")\nu = mesh.create_symbol(\"u\")\nd2_dx2, d2_dy2 = [SymbolicDiff(mesh, axis=k, degree=2) for k in range(2)]\n\n(\n    d2_dx2(u, at=(m, n), offsets=(-1, 0, 1)) + \n    d2_dy2(u, at=(m, n), offsets=(-1, 0, 1))\n)\n```\n\nOutputs:\n\n$$\n\\frac{u_{m,n + 1} + u_{m,n - 1} - 2 u_{m,n}}{\\Delta y^2}  + \\frac{u_{m + 1,n} + u_{m - 1,n} - 2 u_{m,n}}{\\Delta x^2}\n$$\n\nAlso see the [example notebook](examples/symbolic.ipynb).\n\n## Partial Differential Equations\n\n_findiff_ can be used to easily formulate and solve partial differential equation problems\n\n$$\n\\mathcal{L}u(\\vec{x}) = f(\\vec{x})\n$$\n\nwhere $\\mathcal{L}$ is a general linear differential operator.\n\nIn order to obtain a unique solution,  Dirichlet, Neumann or more general boundary conditions\ncan be applied.\n\n### Boundary Value Problems\n\n#### Example 1: 1D forced harmonic oscillator with friction\n\nFind the solution of\n\n$$\n\\left( \\frac{d^2}{dt^2} - \\alpha \\frac{d}{dt} + \\omega^2 \\right)u(t) = \\sin{(2t)}\n$$\n\nsubject to the (Dirichlet) boundary conditions\n\n$$\nu(0) = 0, \\hspace{1em} u(10) = 1\n$$\n\n```python\nfrom findiff import Diff, Id, PDE\n\nshape = (300, )\nt = numpy.linspace(0, 10, shape[0])\ndt = t[1]-t[0]\n\nL = Diff(0, dt)**2 - Diff(0, dt) + 5 * Id()\nf = numpy.cos(2*t)\n\nbc = BoundaryConditions(shape)\nbc[0] = 0\nbc[-1] = 1\n\npde = PDE(L, f, bc)\nu = pde.solve()\n```\n\nResult:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"docs/frontpage/ho_bvp.jpg\" alt=\"ResultHOBVP\" height=\"300\"/\u003e\n\u003c/p\u003e\n\n#### Example 2: 2D heat conduction\n\nA plate with temperature profile given on one edge and zero heat flux across the other\nedges, i.e.\n\n$$\n\\left( \\frac{\\partial^2}{\\partial x^2} + \\frac{\\partial^2}{\\partial y^2} \\right) u(x,y) = f(x,y)\n$$\n\nwith Dirichlet boundary condition\n\n$$\n\\begin{align*}\nu(x,0) \u0026= 300 \\\\\nu(1,y) \u0026= 300 - 200y\n\\end{align*}\n$$\n\nand Neumann boundary conditions\n\n$$\n\\begin{align*}\n\\frac{\\partial u}{\\partial x} \u0026= 0, \u0026 \\text{ for } x = 0 \\\\\n\\frac{\\partial u}{\\partial y} \u0026= 0, \u0026 \\text{ for } y = 0\n\\end{align*}\n$$\n\n```python\nshape = (100, 100)\nx, y = np.linspace(0, 1, shape[0]), np.linspace(0, 1, shape[1])\ndx, dy = x[1]-x[0], y[1]-y[0]\nX, Y = np.meshgrid(x, y, indexing='ij')\n\nL = FinDiff(0, dx, 2) + FinDiff(1, dy, 2)\nf = np.zeros(shape)\n\nbc = BoundaryConditions(shape)\nbc[1,:] = FinDiff(0, dx, 1), 0  # Neumann BC\nbc[-1,:] = 300. - 200*Y   # Dirichlet BC\nbc[:, 0] = 300.   # Dirichlet BC\nbc[1:-1, -1] = FinDiff(1, dy, 1), 0  # Neumann BC\n\npde = PDE(L, f, bc)\nu = pde.solve()\n```\n\nResult:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"docs/frontpage/heat.png\"/\u003e\n\u003c/p\u003e\n\n## Citations\n\nYou have used *findiff* in a publication? Here is how you can cite it:\n\n\u003e M. Baer. *findiff* software package. URL: https://github.com/maroba/findiff. 2018\n\nBibTeX entry:\n\n```\n@misc{findiff,\n  title = {{findiff} Software Package},\n  author = {M. Baer},\n  url = {https://github.com/maroba/findiff},\n  key = {findiff},\n  note = {\\url{https://github.com/maroba/findiff}},\n  year = {2018}\n}\n```\n\n## Development\n\n### Set up development environment\n\n- Fork the repository\n- Clone your fork to your machine\n- Install in development mode:\n\n```\npip install -e .\n```\n\n### Running tests\n\nFrom the console:\n\n```\npip install pytest\npytest tests\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaroba%2Ffindiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaroba%2Ffindiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaroba%2Ffindiff/lists"}