Package: fdint
Fermi-Dirac Integrals (FDINT)FDINT is a free, open-source python package that provides fast, double
precision (64-bit floating point) approximations to the Fermi-Dirac
integrals of integer and half integer order, based on the work by
Prof. Fukushima [1-3]. FDINT is written predominantly inCython, which
is compiled to native code through an intermediate C source, resulting
in C-like performance.[1]T. Fukushima, “Precise and fast computation of Fermi-Dirac integral of
integer and half integer order by piecewise minimax rational approximation,”
Applied Mathematics and Computation, vol. 259, pp. 708-729, May 2015.
DOI: 10.1016/j.amc.2015.03.009[2]T. Fukushima, “Precise and fast computation of inverse Fermi-Dirac
integral of order 1/2 by minimax rational function approximation,”
Applied Mathematics and Computation, vol. 259, pp. 698-707, May 2015.
DOI: 10.1016/j.amc.2015.03.015[3]T. Fukushima, “Precise and fast computation of generalized Fermi-Dirac
integral by parameter polynomial approximation,” 2014.
DOI: 10.13140/2.1.1094.6566Thesource codeanddocumentation(coming soon) are graciously hosted
by GitHub.InstallationIn order to use FDINT, you must have a workingPythondistribution
installed. Python 3 support has not yet been tested, so Python 2.7 is
suggested. You will also need to installNumpybefore proceeding. If
you’re not familiar with Python, you might consider installing aPython distributionthat comes prepackaged with Numpy.From PyPiThis is the recommended method for installing FDINT.PyPiis the python
package index, which contains many python packages that can be easily installed
with a single command. To install FDINT fromPyPi, open up a command
prompt and run the following command:pip install fdintFrom GithubTo install the latest release of FDINT from Github, go to theFDINT releases page, download the latest.zipor.tar.gzsource package, extract its contents, and runpython setup.py installfrom within the extracted directory.TestingOnce installed, you can test the package by running the following command:python -m fdint.testsIf you haveMatplotlibinstalled, you can also plot a sample of the
available functions by running the following command:python -m fdint.examples.plotTutorialFirst, start up an interactive python shell from the command line:$ pythonNext, import everything from thefdintpackage:>>> from fdint import *Now you can access the Fermi-Dirac integral and derivative convenience
functions,fdkanddfdk:>>> fdk(k=0.5,phi=-10)
4.0233994366893939e-05
>>> fdk(0.5,-10)
4.0233994366893939e-05
>>> fdk(k=0.5,phi=5)
7.837976057293096
>>> fdk(k=0.5,phi=50)
235.81861512588432
>>> dfdk(k=0.5,phi=-10) # first derivative
4.0233348580568672e-05You can also pass in numpy arrays as phi:>>> import numpy
>>> fdk(k=0.5,phi=numpy.linspace(-100,10,3))
array([  3.29683149e-44,   2.53684104e-20,   2.13444715e+01])If you request an order or derivative that is not implemented, a
NotImplementedError is raised:>>> fdk(1,0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "fdint/__init__.py", line 50, in fdk
    raise NotImplementedError()
NotImplementedErrorFor semiconductor calculations,parabolic,dparabolic,iparabolic,nonparabolic, anddnonparabolicare provided:>>> parabolic(0)
0.7651470246254078
>>> dparabolic(0)
0.6048986434216304
>>> iparabolic(.7)
-0.11156326391089397
>>> nonparabolic(0,0)
0.7651470705342294
>>> nonparabolic(0,0.07) # InAs
1.006986898726782
>>> dnonparabolic(0,0.07) # InAs
0.8190058991462952BenchmarksBelow are a few benchmarking runs. First,numpy.exp:$ python -m timeit -s "import numpy; from numpy import exp; x=numpy.linspace(-100,10,10000)" "exp(x)"
10000 loops, best of 3: 72.6 usec per loopThe same arguments to the Fermi-Dirac integral of order k=1/2,fdint.fd1h,
takes only ~2.2x the runtime:$ python -m timeit -s "from fdint import fd1h; import numpy; x=numpy.linspace(-100,10,10000)" "fd1h(x)"
10000 loops, best of 3: 158 usec per loopSimilarly, the inverse Fermi-Dirac integral of order k=1/2,fdint.ifd1h,
takes only ~2.4x the runtime ofnumpy.log:$ python -m timeit -s "import numpy; from numpy import exp,log; x=numpy.linspace(-100,10,10000);y=exp(x)" "log(y)"
10000 loops, best of 3: 69.9 usec per loop
$ python -m timeit -s "from fdint import fd1h,ifd1h; import numpy; x=numpy.linspace(-100,10,10000);y=fd1h(x)" "ifd1h(y)"
10000 loops, best of 3: 178 usec per loopThe generalized Fermi-Dirac integrals are also quite fast. For order
k=1/2 with zero nonparabolicity,fdint.gfd1htakes only ~3.7x the runtime
ofnumpy.expfor zero nonparabolicity:$ python -m timeit -s "from fdint import gfd1h; import numpy; x=numpy.linspace(-100,10,10000);b=numpy.zeros(10000);b.fill(0.)" "gfd1h(x,b)"
1000 loops, best of 3: 266 usec per loopHowever, if there is significant nonparabolicity,fdint.gfd1hcan take a
up to ~10x longer thannumpy.exp:$ python -m timeit -s "from fdint import gfd1h; import numpy; x=numpy.linspace(-100,10,10000);b=numpy.zeros(10000);b.fill(0.1)" "gfd1h(x,b)"
1000 loops, best of 3: 467 usec per loop

$ python -m timeit -s "from fdint import gfd1h; import numpy; x=numpy.linspace(-100,10,10000);b=numpy.zeros(10000);b.fill(0.3)" "gfd1h(x,b)"
/usr/local/Cellar/python/2.7.8_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/timeit.py:6: RuntimeWarning: gfd1h: less than 24 bits of accuracy
1000 loops, best of 3: 696 usec per loopThe full calculation for a nonparabolic band takes ~5-17x longer thannumpy.exp, depending on the level of nonparabolicity (Note: for
some reason the timing for this command is unreasonably high when timed
from the command line. When timed inside of ipython, it works fine):$ ipython
In [1]: from fdint import *

In [2]: import numpy

In [3]: phi = numpy.linspace(-100,10,10000)

In [4]: %timeit numpy.exp(phi)
10000 loops, best of 3: 72.9 µs per loop

In [5]: %timeit parabolic(phi)
10000 loops, best of 3: 165 µs per loop

In [6]: alpha = numpy.empty(10000); alpha.fill(0.0) # parabolic

In [7]: %timeit nonparabolic(phi, alpha)
1000 loops, best of 3: 346 µs per loop

In [8]: alpha = numpy.empty(10000); alpha.fill(0.07) # InAs

In [9]: %timeit nonparabolic(phi, alpha)
1000 loops, best of 3: 695 µs per loop

In [10]: alpha = numpy.empty(10000); alpha.fill(0.15) # InSb

In [11]: %timeit nonparabolic(phi, alpha)
/usr/local/bin/ipython:257: RuntimeWarning: nonparabolic: less than 24 bits of accuracy
1000 loops, best of 3: 1.26 ms per loopDocumentationThedocumentation(coming soon) is graciously hosted by GitHub.