8

I want to plot a vibrating membrane and therefor I need the bessel functions. As I'm using pgfplots, I wondered if there is anything pgf-related that can be used to create a corresponding output. I'm providing a MWE for playing around with the package.

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
  \begin{tikzpicture}
    \begin{axis}
      \addplot3[surf, z buffer=sort, domain=0:1, y domain=0:2*pi]
        ({x * cos(deg(y))}, {x * sin(deg(y))}, {cos(pi*x)});
    \end{axis}
  \end{tikzpicture}
\end{document}

Has anybody a workaround or a way of using the functions?

9

Remarks

pgfplots offers to use the external programme gnuplot through

\addplot gnuplot {<gnuplot stuff>};

Review section 4.3.5 "Computing Coordinates with Mathematical Expressions" on page 56 of the pgfplots 1.9 manual.

gnuplot provides the function besj0(r), that return the Bessel J0 function.

Implementation

Use arara or pdflatex -shell-escape. You need gnuplot in your $PATH.

% arara: pdflatex: { shell: yes }
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
    \begin{axis}
        \addplot3[surf,z buffer=sort,domain=-2:2,y domain=-2:2] gnuplot {besj0(x**2+y**2)};
    \end{axis}
\end{tikzpicture}
\end{document}

Output

enter image description here


You can also use the FFI in LuaJITTeX (and LuaTeX ≥ 1.0.3) to access the Bessel function in libm directly. The performance and accuracy are simply amazing! The BesselJ function takes two arguments where the first is the order of the Bessel function, i.e. all orders are directly accessible without having to use recurrence relations.

\documentclass{article}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}

\directlua{
  ffi=require("ffi")
  ffi.cdef[[
  double jn(int n, double x);
  ]]
}

\pgfmathdeclarefunction{BesselJ}{2}{%
  \edef\pgfmathresult{%
    \directlua{tex.print(ffi.C.jn(\pgfmathfloatvalueof{#1},\pgfmathfloatvalueof{#2}))}%
  }%
}

\begin{document}

\begin{tikzpicture}
  \begin{axis}
    \addplot3[surf,z buffer=sort,domain=-2:2,y domain=-2:2] { BesselJ(0,x^2+y^2)) };
  \end{axis}
\end{tikzpicture}

\end{document}
2
  • 2
    Thanks a lot, that's pretty much everything I could ever desire. Except: I didn't find any way in gnuplot to use J_2. I did only find the functions besj0 and besj1. Is there any more general approach like besj(n, x) or something similar?
    – Guest
    Feb 16 '14 at 15:08
  • @HenriMenke: It may be worthwhile adding a note that one needs lualatex -shell-escape to run code with FFI.
    – Aditya
    Aug 15 '19 at 11:02
4

With PSTricks just for fun.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-func,amsmath}

\psset{xunit=0.25,yunit=5}
\begin{document}
\begin{pspicture}(-28,-.75)(29,1.2)
\rput(13,0.8){$\displaystyle J_n(x)=\frac{1}{\pi}\int_0^\pi\cos(x\sin t-nt)\,\mathrm{d}t$}
\psaxes[Dy=0.2,Dx=4]{->}(0,0)(-28,-.75)(28.5,1.15)[$x$,0][$y$,90]
\psset{linewidth=1pt}
\psBessel[linecolor=red]{0}{-28}{28}%
\psBessel[linecolor=blue]{1}{-28}{28}%
\psBessel[linecolor=green]{2}{-28}{28}%
\psBessel[linecolor=magenta]{3}{-28}{28}%
\end{pspicture}
\end{document}

enter image description here

2
  • Very impressive, thanks. I didn't know that PSTricks was this powerful!
    – Guest
    Feb 16 '14 at 15:06
  • 2
    A \, before \mathrm{d} would be appropriate. Feb 22 '14 at 15:44
4

Here is a MWE:

\documentclass[12pt]{article}
\usepackage{pgfplots}
\usepackage{tikz}


\begin{document}
  \begin{tikzpicture}
    \begin{axis}[width=\textwidth, height=0.5*\textwidth, xlabel=$x$]
    \addplot+[id=parable,domain=0:20, samples=500, mark=none, width=2pt]
    gnuplot{besj0(x)} node[pin=95:{$J_0(x)$}]{};
    \addplot+[id=parable,domain=0:20, samples=500, mark=none, width=2pt, color=red]
    gnuplot{besj1(x)} node[pin=130:{$J_1(x)$}]{};
    \addplot+[id=parable2,domain=0:20, samples=500, mark=none, width=2pt, color=black]
    gnuplot{2*1/x*besj1(x)-besj0(x)} node[pin=-140:{$J_2(x)$}]{};
   \end{axis}
  \end{tikzpicture}
\end{document}

Please run with "pdflatex -shell-escape"

Here is the figure:

enter image description here

2

Possible to use GNUplot for higher order Bessel's function also. One can use the recurrence formulas, http://www.encyclopediaofmath.org/index.php/Bessel_functions

%For examples, plotting besj2(x)

\addplot[color=yellow,
solid,
line width=1.0pt,
%mark=asterisk,
%mark options={solid},
domain=0:5,samples=400]
gnuplot {abs(2*1/x * besj1(x) - besj0(x))};

%Similarly besj3(x) gnuplot {abs(2*2/x * besj2(x) - besj1(x))};

Bessel's functions using GNUplot and pgfplots

1
  • Thank you, that's actually really helpful! I didn't think of this forumla.
    – Guest
    Feb 22 '14 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.