finitediff
==========
.. image:: http://hera.physchem.kth.se:9090/api/badges/bjodah/finitediff/status.svg
   :target: http://hera.physchem.kth.se:9090/bjodah/finitediff
   :alt: Build status
.. image:: https://img.shields.io/pypi/v/finitediff.svg
   :target: https://pypi.python.org/pypi/finitediff
   :alt: PyPI version
.. image:: https://zenodo.org/badge/14988640.svg
   :target: https://zenodo.org/badge/latestdoi/14988640
   :alt: Zenodo DOI
.. image:: https://img.shields.io/badge/python-2.7,3.4,3.5-blue.svg
   :target: https://www.python.org/
   :alt: Python version
.. image:: https://img.shields.io/pypi/l/finitediff.svg
   :target: https://github.com/bjodah/finitediff/blob/master/LICENSE
   :alt: License
.. image:: http://hera.physchem.kth.se/~finitediff/branches/master/htmlcov/coverage.svg
   :target: http://hera.physchem.kth.se/~finitediff/branches/master/htmlcov
   :alt: coverage

``finitediff`` containts three implementations of Begnt Fornberg's
formulae for generation of finite difference weights on aribtrarily
spaced one dimensional grids:

- `C89 <src/finitediff_c.c>`_
- `Fortran 90 <src/finitediff_fort.f90>`_
- `C++ <finitediff/include/finitediff_templated.hpp>`_

The finite difference weights can be
used for optimized inter-/extrapolation data series for up to
arbitrary derivative order. Python_ bindings (to the C versions) are also provided.

.. _Python: https://www.python.org
.. _finitediff: https://github.com/bjodah/finitediff


Capabilities
============
``finitediff`` currently provides callbacks for estimation of derivatives
or interpolation either at a single point or over an array (available
from the Python bindings).

The user may also manually generate the corresponding weights. (see
``calculate_weights``)

Finitediff can be conditionally compiled to make ``finitediff_interpolate_by_finite_diff``
multithreaded. Then the number of threads used is set through the environment variable
``FINITEDIFF_NUM_THREADS`` (or ``OMP_NUM_THREADS``).


Documentation
-------------
Autogenerated API documentation for latest stable release is found here:
`<https://bjodah.github.io/finitediff/latest>`_
(and the development version for the current master branch is found here:
`<http://hera.physchem.kth.se/~finitediff/branches/master/html>`_).

Examples
--------
Generating finite difference weights is simple using C++11:

.. code:: C++

   #include "finitediff_templated.hpp"
   #include <vector>
   #include <string>
   #include <iostream>

   int main(){
       const unsigned max_deriv = 2;
       std::vector<std::string> labels {"0th derivative", "1st derivative", "2nd derivative"};
       std::vector<double> x {0, 1, -1, 2, -2};  // Fourth order of accuracy
       auto coeffs = finitediff::generate_weights(x, max_deriv);
       for (unsigned deriv_i = 0; deriv_i <= max_deriv; deriv_i++){
           std::cout << labels[deriv_i] << ": ";
           for (unsigned idx = 0; idx < x.size(); idx++){
               std::cout << coeffs[deriv_i*x.size() + idx] << " ";
           }
           std::cout << std::endl;
       }
   }


::

   $ cd examples/
   $ g++ -std=c++11 demo.cpp -I../include
   $ ./a.out
   Zeroth derivative (interpolation): 1 -0 0 0 -0
   First derivative: -0 0.666667 -0.666667 -0.0833333 0.0833333
   Second derivative: -2.5 1.33333 1.33333 -0.0833333 -0.0833333


and of course using the python bindings:

.. code:: python

   >>> from finitediff import get_weights
   >>> import numpy as np
   >>> c = get_weights(np.array([0, -1., 1]), 0, maxorder=1)
   >>> np.allclose(c[:, 1], [0, -.5, .5])
   True


from Python you can also use the finite differences to interpolate
values (or derivatives thereof):

.. code:: python

    >>> from finitediff import interpolate_by_finite_diff as ifd
    >>> x = np.array([0, 1, 2])
    >>> y = np.array([[2, 3, 5], [3, 4, 7], [7, 8, 9], [3, 4, 6]])
    >>> xout = np.linspace(0.5, 1.5, 5)
    >>> r = ifd(x, y, xout, maxorder=2)
    >>> r.shape
    (5, 4, 3)


see the ``examples/`` directory for more examples.

Installation
------------
You can install ``finitediff`` by using ``pip``::

   $ python -m pip install --user finitediff

(you can skip the ``--user`` flag if you have got root permissions),
to run the tests you need ``pytest`` too::

   $ python -m pip install --user --upgrade pytest
   $ python -m pytest --pyargs finitediff

alternatively (on Linux) you may also use
`conda package manager <http://conda.pydata.org/docs/>`_::

   $ conda install -c bjodah finitediff pytest


Dependencies
============
You need either a C, C++ or a Fortran 90 compiler. On debian based linux systems you may install (all) by issuing::

    $ sudo apt-get install gfortran g++ gcc

See `setup.py <setup.py>`_ for optional (Python) dependencies.


References
==========
The algortihm is a rewrite of:

http://dx.doi.org/10.1137/S0036144596322507

::

    @article{fornberg_classroom_1998,
      title={Classroom note: Calculation of weights in finite difference formulas},
      author={Fornberg, Bengt},
      journal={SIAM review},
      volume={40},
      number={3},
      pages={685--691},
      year={1998},
      publisher={SIAM}
      doi={10.1137/S0036144596322507}
    }


Which is based on an article of the same author:

http://dx.doi.org/10.1090/S0025-5718-1988-0935077-0

::

    @article{fornberg_generation_1988,
      title={Generation of finite difference formulas on arbitrarily spaced grids},
      author={Fornberg, Bengt},
      journal={Mathematics of computation},
      volume={51},
      number={184},
      pages={699--706},
      year={1988}
      doi={10.1090/S0025-5718-1988-0935077-0}
    }


License
=======
The source code is Open Source and is released under the very permissive
`"simplified (2-clause) BSD license" <https://opensource.org/licenses/BSD-2-Clause>`_.
See `LICENSE <LICENSE>`_ for further details.


Authors
=======
See file `AUTHORS <AUTHORS>`_ in root.
