{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Special Functions\n", "\n", "This tutorial shows interfaces and examples of [special_functions](https://ameli.github.io/special_functions) package.\n", "\n", "* [Python Interface](#Python-Interface)\n", "* [Examples in Python](#Examples-in-Python)\n", "* [Cython Interface](#Cython-Interface)\n", "* [Examples in Cython](#Examples-in-Cython)\n", "\n", "## Python Interface\n", "\n", "| Syntax | Return type | Symbol | Description |\n", "|:------ |:----------- |:------ |:----------- |\n", "| `besselj(nu, z, n)` | `double`, `double complex` | $$\\partial^n J_{\\nu}/\\partial z^n$$ | [Bessel function of the first kind](https://ameli.github.io/special_functions/besselj.html) |\n", "| `bessely(nu, z, n)` | `double`, `double complex` | $$\\partial^n Y_{\\nu}/\\partial z^n$$ | [Bessel function of the second kind (Weber function)](https://ameli.github.io/special_functions/bessely.html) |\n", "| `besseli(nu, z, n)` | `double`, `double complex` | $$\\partial^n I_{\\nu}/\\partial z^n$$ | [Modified Bessel function of the first kind](https://ameli.github.io/special_functions/besseli.html) |\n", "| `besselk(nu, z, n)` | `double`, `double complex` | $$\\partial^n I_{\\nu}/\\partial z^n$$ | [Modified Bessel function of the second kind](https://ameli.github.io/special_functions/besselk.html) |\n", "| `besselh(nu, k, z, n)` | `double complex` | $$\\partial^n H^{(k)}_{\\nu}/\\partial z^n$$ | [Bessel function of the third kind (Hankel function)](https://ameli.github.io/special_functions/besselh.html) |\n", "| `loggamma(nu, x, n)` | `double` | $$\\log \\Gamma(x)$$ | [Natural logarithm of Gamma function](https://ameli.github.io/special_functions/loggamma.html) |\n", "\n", "#### Input Arguments\n", "\n", "| Variable | Type(s) | Symbol | Description |\n", "|:-------- |:------- |:------ |:----------- |\n", "| `nu` | `double` | $$\\nu$$ | The parameter of the Bessel functions. |\n", "| `k` | `int` | $$k$$ | Canbe either `1` and `2` and determines the type of Hankel function. |\n", "| `z` | `double`, `double complex` | $$z$$ | The real or complex input argument of the Bessel functions. |\n", "| `x` | `double` | $$x$$ | The real input argument of functions. |\n", "\n", "\n", "## Examples in Python\n", "\n", "In the example below, we compute the modified Bessel function of the second kind $ \\partial^n K_{\\nu}(z) / \\partial z^n$ where $\\nu$ is the parameter of the Bessel function, $z$ can be real or complex, and $n$ is the order of the derivative of the function. $n = 0$ means no derivative." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.17990665795209218" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import special_functions as sf\n", "nu = 1.5\n", "z = 2.0\n", "n = 0\n", "sf.besselk(nu, z, n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we try a complex argument $z = 2 + j$ (where $j^2 = -1$) and the first derivative of the function:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(-0.00937048840778705+0.21078407796464216j)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "z = 2.0 + 1.0j\n", "n = 1\n", "sf.besselk(nu, z, n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cython Interface\n", "\n", "In Cython, there are two syntaxes for each function depending on whether the input argument is real or complex.\n", "\n", "* For real arguments, the syntaxes are the same as the Python interface. For example: ``besselk``.\n", "* For complex arguments, add the letter `c` to the begining of the function, for example: ``cbesselk``.\n", "\n", "The table below shows the function signatures for real and complex cases:\n", "\n", "| Real functions | Complex functions |\n", "|:-------------- |:----------------- |\n", "| `double besselj(double nu, double x, int n)` | `double complex cbesselj(double nu, double complex z, int n)` |\n", "| `double bessely(double nu, double x, int n)` | `double complex cbessely(double nu, double complex z, int n)` |\n", "| `double besseli(double nu, double x, int n)` | `double complex cbesseli(double nu, double complex z, int n)` |\n", "| `double besselk(double nu, double x, int n)` | `double complex cbesselk(double nu, double complex z, int n)` |\n", "| `double complex besselh(double nu, int k, double x, int n)` | `double complex cbesselh(double nu, int k, double complex z, int n)` |\n", "| `double loggamma(double x)` | N/A |\n", "\n", "## Examples in Cython" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The Cython extension is already loaded. To reload it, use:\n", " %reload_ext Cython\n" ] } ], "source": [ "%load_ext Cython" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.17990665795209218\n" ] } ], "source": [ "%%cython\n", "\n", "# Use this in a *.pyx file\n", "cimport special_functions as sf\n", "\n", "# Declare typed input variables\n", "cdef double nu = 1.5\n", "cdef double x = 2.0\n", "cdef int n = 0\n", "\n", "# Declare typed output variable\n", "cdef double K_real\n", "\n", "# The 'nogil' statement below is optional.\n", "with nogil:\n", " K_real = sf.besselk(nu, x, n)\n", "\n", "# Print the output\n", "print(K_real)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we try the same code in the above, but for the complex argument $z = 2.0 + j$." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0.031409508972862196-0.157309366284669j)\n" ] } ], "source": [ "%%cython\n", "\n", "# Use this in a *.pyx file\n", "cimport special_functions as sf\n", "\n", "# Declare typed input variables\n", "cdef double nu = 1.5\n", "cdef double complex z = 2.0 + 1.0j\n", "cdef int n = 0\n", "\n", "# Declare typed output variable\n", "cdef double complex K_complex\n", "\n", "# The 'nogil' statement below is optional.\n", "with nogil:\n", " K_complex = sf.cbesselk(nu, z, n)\n", "\n", "print(K_complex)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12" } }, "nbformat": 4, "nbformat_minor": 4 }