5

I'm trying to plot Planck's law using tikz. This works fine for the most part, but tikz thinks I'm dividing by 0 if I try to plot certain areas of the law. Here's a minimally working example of what I'm trying to do :

\documentclass[8pt,xcolor=dvipsnames,compress]{beamer}
\usepackage{tikz}
\begin{document}
\begin{frame}
  \begin{tikzpicture}
    \draw[->] (0,0) -- (4.2,0) node[right] {$\lambda$};
    \draw[->] (0,0) -- (0,4.2) node[above] {Flux};
    \draw[scale=3,domain=0.16:1,smooth,variable=\x,blue] plot ({\x},{((1/(exp(1/\x)-1)*(1/(\x^5)))/20});
    \end{tikzpicture}
  \end{frame}
\end{document}

Now this works, but notice that my domain start at 0.16. I'd like it to start earlier, at least around 0.1, but if I start my domain at 0.1 I get a division by 0 error :

! Package PGF Math Error: You've asked me to divide `1' by `0.0', but I cannot divide any number by `0.0' (in '{((1/(exp(1/0.1)-1)*(1/(0.1^5)))/20}').

Any ideas as to what's causing this ?

Andrew Swann
  • 95,762
ticster
  • 319

2 Answers2

8

You need to make sure that the fpu library is used so that arithmetic is does with floating point numbers. The easiest way to do this is to use pgfplots ( built on top of tikz), which will do this by default.

In pgfplots the default style for axes are boxed, so some tweaking is needed to produce the style of plot you are after. But the actual plotting command for the function is simple.

Sample output

\documentclass[8pt,xcolor=dvipsnames,compress]{beamer}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\begin{document}

\begin{frame}
  \begin{tikzpicture}
    \begin{axis}[xlabel={\( \lambda \)},ylabel={Flux},
      axis x line=bottom,axis y line=left,
      every axis x label/.append style={at={(1,0)},right},
      every axis y label/.append style={at={(0,1)},above,rotate=-90}]
      \addplot[blue,domain=0.01:1,samples=200]
      {1/((exp(1/x)-1)*x^5*20)};
    \end{axis}
    \end{tikzpicture}
  \end{frame}

\end{document}
Andrew Swann
  • 95,762
  • Maybe we should mention that TikZ v3 also works without any problems. So it is not solely the fpu library requirement but due to a bug in v2.10. – percusse Jun 02 '15 at 08:16
  • @percusse I tried the posters original code with my tikz.sty 2013/12/13 v3.0.0 (rcs-revision 1.142) and got overflow errors (rather than division by zero). I await TL2015 to test newer versions. – Andrew Swann Jun 02 '15 at 08:28
  • Ah, yes my wrong wording. It goes back to the regular TeX behavior with TikZ v3 instead of divide by zero mistake. – percusse Jun 02 '15 at 08:36
  • Thank you for the answer. I should point out for future readers that \uncover doesn't work properly when used around \addplot (and \addplot<i-j> doesn't work at all) so I had to use \only, and to make sure my plots didn't jump around drew a white (therefore invisible) plot that was the size of my plot with the biggest dimensions, therefore setting the axes to be the same throughout my slides. – ticster Jun 02 '15 at 10:16
  • Glad this helped. Specifying common sizes for axes is a good way to get uniform plots. bemear has the overlayarea environment to help with placement too. – Andrew Swann Jun 02 '15 at 10:42
6

You have x5 in the denominator with 0.1 as smallest value. The precision of TeX's arithmetic via dimen registers in unit pt is only 2-16 (= 1 sp). Therefore, 0.15 becomes 0.00001 and 0.00001 pt is smaller than 1 sp and the result is truncated to zero.

TikZ supports better arithmetics, e.g., via library fpu, see the other answer of Andrew Swann. This example shows the use of library fixedpointarithmetic, which relies on package fp. The calculations take more time, but the result is more precise and the lower limit can be decreased to 0.025 before arithmetic overflow. I have also increased the number of samples to get a better curve shape.

\documentclass[8pt,xcolor=dvipsnames,compress]{beamer}
\usepackage{tikz}
\usepackage{fp}
\usetikzlibrary{fixedpointarithmetic}
\begin{document}
\begin{frame}
  \begin{tikzpicture}
    \draw[->] (0,0) -- (4.2,0) node[right] {$\lambda$};
    \draw[->] (0,0) -- (0,4.2) node[above] {Flux};
    \draw[
      samples=100,
      fixed point arithmetic,
      scale=3,domain=0.025:1,smooth,variable=\x,blue] plot
    ({\x},{((1/(exp(1/\x)-1)*(1/(\x^5)))/20});
    \end{tikzpicture}
  \end{frame}
\end{document}

Result

Heiko Oberdiek
  • 271,626
  • samples=100 cannot be used after fixed point arithmetic because of a bug in function max. I made a bug report. – Heiko Oberdiek Jun 02 '15 at 09:27
  • Thank you for the answer. However, this does indeed take too long to calculate and given how often I compile my slides to check how they turn out, I'm going to go with the other answer. But thanks a lot for the details. – ticster Jun 02 '15 at 10:14