50

This question led to a new package:
bohr

I'm making slides with beamer for my chemistry students. I would like to draw a figure in LaTeX to illustrate the electron shells in the Bohr model but I cant find any chemistry package that does that? Is the only way to do it to use TikZ or something and do it manually? Somebody must have had this need before?

4
  • 1
    Can you please upload (or provide a link to) an image of the figure you want? Commented Sep 20, 2012 at 21:13
  • @GonzaloMedina: Bohr model. The nucleus in the middle and rings around it that represent electron shells “similar in structure to the solar system”. (Here are more pictures)
    – cgnieder
    Commented Sep 20, 2012 at 21:20
  • 1
    I can't help it but I have to comment that I was really frustrated to find out in the last year of high school that the Bohr model is quite misleading. A lot of organic chemistry does not make any sense without the knowledge about s-, p- and d-orbitals, so please do not use this model for chemistry students as they have to unlearn it later.
    – Alexander
    Commented Sep 21, 2012 at 15:25
  • 3
    @Alexander I disagree. When taught right one can easily interpret the orbitals as refinement of the shells. The shells still correspond to the principal quantum number
    – cgnieder
    Commented Sep 23, 2012 at 15:06

4 Answers 4

47

Gonzalo's version is really nice, Harish's is even stable and Garbage Collector's version is animated. So a have a different motivation. The code below defines a macro \bohr that doesn't draw protons and neutrons (chemists are mostly interested in the electron configuration, most isotopes behave nearly identical, chemically speaking) but instead allows to draw simple Bohr models for atoms up to the atomic number 54.

\bohr[<number of shells>]{<number of electrons>}{<name of atom>}

If the first argument is not given it is derived from the number of electrons.

Let's see how it works first:

\documentclass{article}
\usepackage{bohr}
\begin{document}

\bohr{11}{Na}
\bohr{28}{Ni}

\setbohr{name-options-set={font=\footnotesize\sffamily}}
\bohr{18}{Ar}
\bohr{2}{He}
\bohr{7}{F}% damn, that should have been N...

\setbohr{nucleus-radius=1.2em}
\bohr[3]{10}{$\mathrm{Na^+}$}

\end{document}

enter image description here

I've added a few options to make the appearance customizable...

Now the code for bohr.sty:

\ProvidesPackage{bohr}[2012/09/21 v0.1 simple atom representation according to the Bohr model]
\RequirePackage{tikz,etoolbox}

\newrobustcmd*\bohr[3][]{\@bohr{#1}{#2}{#3}}

\def\@bohr#1#2#3{%
  \ifblank{#1}
    {\@bohr@get@shell@num{#2}}
    {\def\@bohr@shell@num{#1}}%
  \tikzpicture[baseline=(nucleus.base)]
    \expandafter\node\expandafter[\@bohr@name@options]
      (nucleus) at (0,0) {#3} ;
    \expandafter\draw\expandafter[\@bohr@nucleus@options]
      (nucleus) circle (\@bohr@nucleus@radius) ;
    \foreach\@bohr@current@shell@num in {1,...,\@bohr@shell@num}
      {
        \expandafter\draw\expandafter[\@bohr@shell@options]
          (nucleus) circle (\@bohr@nucleus@radius+\@bohr@current@shell@num*\@bohr@shell@dist) ;
      }
    \@bohr@draw@electrons{#2}
  \endtikzpicture
}

\def\@bohr@get@shell@num#1{%
  \ifnum#1<3\relax
    \def\@bohr@shell@num{1}%
  \else
    \ifnum#1<11\relax
      \def\@bohr@shell@num{2}%
    \else
      \ifnum#1<19\relax
        \def\@bohr@shell@num{3}%
      \else
        \ifnum#1<37\relax
          \def\@bohr@shell@num{4}%
        \else
          \ifnum#1<55\relax
            \def\@bohr@shell@num{5}%
          \else
            \@bohr@error{I don't know how to draw #1 electrons!}%
          \fi
        \fi
      \fi
    \fi
  \fi
}

\def\@bohr@distribute@electrons#1#2#3#4{%
  \foreach\@bohr@electron@number in {#1,...,#2}
    {
      \expandafter\fill\expandafter[\@bohr@electron@options] (nucleus)
        ++(#3*\@bohr@electron@number:\@bohr@nucleus@radius+#4*\@bohr@shell@dist)
        circle (\@bohr@electron@radius) ;
    }
}

\def\@bohr@draw@electrons#1{%
  \ifnum#1<3\relax
    \@bohr@distribute@electrons{1}{#1}{180}{1}%
  \else
    \ifnum#1<11\relax
      \@bohr@distribute@electrons{1}{2}{180}{1}%
      \@bohr@distribute@electrons{3}{#1}{45}{2}%
    \else
      \ifnum#1<19\relax
        \@bohr@distribute@electrons{1}{2}{180}{1}%
        \@bohr@distribute@electrons{3}{10}{45}{2}%
        \@bohr@distribute@electrons{11}{#1}{45}{3}%
      \else
        \ifnum#1<37\relax
          \@bohr@distribute@electrons{1}{2}{180}{1}%
          \@bohr@distribute@electrons{3}{10}{45}{2}%
          \@bohr@distribute@electrons{11}{18}{45}{3}%
          \@bohr@distribute@electrons{19}{#1}{20}{4}%
        \else
          \ifnum#1<55\relax
            \@bohr@distribute@electrons{1}{2}{180}{1}%
            \@bohr@distribute@electrons{3}{10}{45}{2}%
            \@bohr@distribute@electrons{11}{18}{45}{3}%
            \@bohr@distribute@electrons{19}{36}{20}{4}%
            \@bohr@distribute@electrons{37}{#1}{20}{5}%
          \fi
        \fi
      \fi
    \fi
  \fi
}

% definable parameters:
\def\@bohr@name@options{}
\def\@bohr@nucleus@radius{1em}
\def\@bohr@electron@options{blue!50!black!50}
\def\@bohr@electron@radius{1.5pt}
\def\@bohr@shell@dist{1em}
\def\@bohr@nucleus@options{draw=black!80,fill=black!10,opacity=.25}
\def\@bohr@shell@options{draw=blue!75,thin}

\pgfkeys{
  bohr/.cd,
    name-options-set/.code     = \def\@bohr@name@options{#1} ,
    name-options-add/.code     =
      \expandafter\def\expandafter\@bohr@name@options\expandafter{\@bohr@name@options,#1} ,
    nucleus-radius/.code       = \def\@bohr@nucleus@radius{#1} ,
    nucleus-options-set/.code  = \def\@bohr@nucleus@options{#1} ,
    nucleus-options-add/.code  =
      \expandafter\def\expandafter\@bohr@nucleus@options\expandafter{\@bohr@nucleus@options,#1} ,
    electron-radius/.code      = \def\@bohr@electron@radius{#1} ,
    electron-options-set/.code = \def\@bohr@electron@options{#1} ,
    electron-options-add/.code =
      \expandafter\def\expandafter\@bohr@electron@options\expandafter{\@bohr@electron@options,#1} ,
    shell-dist/.code           = \def\@bohr@shell@dist{#1} ,
    shell-options-set/.code    = \def\@bohr@shell@options{#1} ,
    shell-options-add/.code    =
      \expandafter\def\expandafter\@bohr@shell@options\expandafter{\@bohr@shell@options,#1}
}

\newrobustcmd\setbohr[1]{\pgfqkeys{/bohr}{#1}}

\def\@bohr@error#1{\PackageError{bohr}{#1}{}}
\endinput
8
  • 13
    Really nice package; I guess this is what the OP really needs; you chemists are so bohring ;-). Commented Sep 21, 2012 at 13:55
  • Hi everybody and many thanks for all creative suggestions! I like all of them and I will certainly use them on different occasions. @cgnieder 's suggestion however is the most useful in my everyday situation where I have to produce som slides quickly.
    – Andreas
    Commented Sep 21, 2012 at 14:03
  • 2
    And, @cgnieder - you should really send it in to CTAN - it is very useful!
    – Andreas
    Commented Sep 21, 2012 at 14:17
  • @GonzaloMedina: :-D … or: Haha!
    – Speravir
    Commented Sep 21, 2012 at 20:15
  • @Andreas Here it is :)
    – cgnieder
    Commented Sep 23, 2012 at 10:24
49

This is one possibility using TikZ:

\documentclass{article}
\usepackage{tikz} 
\usetikzlibrary{decorations.markings} 

\definecolor{myyellow}{RGB}{254,241,24}
\definecolor{myorange}{RGB}{234,125,1}

\begin{document}

\begin{tikzpicture}
\def\proton(#1,#2){%
    \fill[shade=ball,ball color=myyellow] (#1,#2) circle (10pt);
    \node at (#1,#2) {\texttt{+}};
}
\def\neutron(#1,#2){%
    \fill[shade=ball,ball color=myorange] (#1,#2) circle (10pt);
}
\def\electron{%
    \fill[shade=ball,ball color=gray!30] (0,0) circle (5pt);
    \node at (0,0) {\texttt{-}};
}
\neutron(0.8,0.2)
\proton(0.5,-0.5)
\neutron(-0.25,-0.5)
\neutron(0.55,0.8)
\proton(-0.5,0.2)
\proton(-0.1,0.8)
\proton(0.5,0)
\proton(0.12,0.6)
\proton(0.12,-0.6)
\neutron(-0.25,0)
\draw[
  postaction=decorate,
  decoration={markings, 
  mark=at position 0.5 with {\electron},
  mark=at position 1 with {\electron}
}] 
  (0,0) circle (2cm);
\draw[
  postaction=decorate,
  decoration={markings, 
  mark=at position 0.3 with {\electron},
  mark=at position 0.55 with {\electron},
  mark=at position 0.85 with {\electron},
  mark=at position 0.75 with {\electron}
}] 
  (0,0) circle (3cm);

\end{tikzpicture}

\end{document} 

enter image description here

12
  • 24
    Oh-Oh! C10 only has a half-life of about 19 seconds! Vote early and fast! :)
    – cgnieder
    Commented Sep 20, 2012 at 22:05
  • 4
    Last vote for the day: happy to still have one.
    – egreg
    Commented Sep 20, 2012 at 22:08
  • 1
    @cgnieder: Clemens, you are nasty! :-)
    – Speravir
    Commented Sep 20, 2012 at 22:35
  • 1
    As far as I know C10 has only been created synthetically. The most common natural carbon is C12 ($6\mathrm{p^+}$ and $6\mathrm{n^0}$)
    – cgnieder
    Commented Sep 20, 2012 at 23:31
  • 1
    @PauloCereda thank you! I even learnt about C10 and its 19sec. half-life. Commented Sep 21, 2012 at 0:29
42

A variation of Gonzalo's code (just for fun). This is stable, hence feel free not to upvote ;).

\documentclass{standalone}
\usepackage{tikz,graphicx}
\usetikzlibrary{decorations.markings}

\definecolor{myyellow}{RGB}{254,241,24}
\definecolor{myorange}{RGB}{234,125,1}

\begin{document}

\begin{tikzpicture}
\def\proton(#1,#2){%
    \fill[shade=ball,ball color=myyellow] (#1,#2) circle (10pt);
    \node at (#1,#2) {\texttt{+}};
}
\def\neutron(#1,#2){%
    \fill[shade=ball,ball color=myorange] (#1,#2) circle (10pt);
}
\def\electron{%
    \fill[shade=ball,ball color=gray!30] (0,0) circle (5pt);
    \node at (0,0) {\texttt{-}};
}
\def\orbit(#1,#2){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,
  mark=at position #2 with {\electron},
}]
  (0,0) ellipse (3 and 5);
}
%%Nucleons
\neutron(0.8,0.2)
\proton(0.5,-0.5)
\neutron(-0.25,-0.5)
\neutron(0.55,0.8)
\proton(-0.5,0.2)
\proton(-0.1,0.8)
\proton(0.5,0)
\proton(0.12,0.6)
\proton(0.12,-0.6)
\neutron(-0.25,0)
\neutron(-0.5,0.6)
\neutron(0.5,-0.3)
%%orbits
\orbit(-20,.15)
\orbit(15,.45)
\orbit(40,.9)
\orbit(65,.6)
\orbit(100,.3)
\orbit(125,.75)

\end{tikzpicture}

\end{document}

enter image description here

Putting the exact shapes of shells is somewhat tricky around a nucleus. But schematicaly differentiating them is trivial as in the following code.

\documentclass{standalone}
\usepackage{tikz,graphicx}
\usetikzlibrary{decorations.markings}

\definecolor{myyellow}{RGB}{254,241,24}
\definecolor{myorange}{RGB}{234,125,1}

\begin{document}

\begin{tikzpicture}
\def\proton(#1,#2){%
    \fill[shade=ball,ball color=myyellow] (#1,#2) circle (10pt);
    \node at (#1,#2) {\texttt{+}};
}
\def\neutron(#1,#2){%
    \fill[shade=ball,ball color=myorange] (#1,#2) circle (10pt);
}
\def\electron{%
    \fill[shade=ball,ball color=gray!30] (0,0) circle (5pt);
    \node at (0,0) {\texttt{-}};
}
\def\sorbit(#1,#2){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,
  mark=at position #2 with {\electron},
}]
  (0,0) ellipse (1.5 and 3.5);
}
\def\porbit(#1,#2){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,
  mark=at position #2 with {\electron},
}]
  (0,0) ellipse (4 and 6);
}
%%Nucleons
\neutron(0.8,0.2)
\proton(0.5,-0.5)
\neutron(-0.25,-0.5)
\neutron(0.55,0.8)
\proton(-0.5,0.2)
\proton(-0.1,0.8)
\proton(0.5,0)
\proton(0.12,0.6)
\proton(0.12,-0.6)
\neutron(-0.25,0)
\neutron(-0.5,0.6)
\neutron(0.5,-0.3)
%%orbits
\porbit(-20,.15)
\porbit(15,.45)
\sorbit(40,.9)
\porbit(65,.6)
\sorbit(100,.3)
\porbit(125,.75)

\end{tikzpicture}

\end{document}

enter image description here

Update - 1

Now, time to have some animation and have fun (I blame it all on @Garbage collector, he spoiled me! ;)..).

The following code will produce an animated pdf, gif and a series of png files. Compile the code with pdflatex -shell-escape filename.tex

\documentclass[preview,border={10pt 0pt 10pt 10pt}]{standalone}
\usepackage{filecontents}
\begin{filecontents*}{atom.tex}
\documentclass[tikz,border=20pt]{standalone}
\usepackage{tikz,graphicx}
\usetikzlibrary{decorations.markings,calc}

\definecolor{myyellow}{RGB}{254,241,24}
\definecolor{myorange}{RGB}{234,125,1}

\def\proton(#1,#2){%
    \fill[shade=ball,ball color=myyellow] ({rnd*#1},{rnd*#2}) circle (10pt) node {\texttt{+}};
}
\def\neutron(#1,#2){%
    \fill[shade=ball,ball color=myorange] ({rnd*#1},{rnd*#2}) circle (10pt);
}
\def\electron{%
    \fill[shade=ball,ball color=gray!30] (0,0) circle (5pt);
    \node at (0,0) {\texttt{-}};
}
\def\orbit(#1,#2,#3){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,pre=moveto,pre length=#3,
  mark=at position {#2} with {\electron},
}]
  (0,0) ellipse (1 and 4);
}
\begin{document}
\foreach \pos in {0,0.08,0.16,...,0.96}{%
\begin{tikzpicture}%
%%Nucleons
\neutron(0.4,0.4)
\proton(0.4,-0.4)
\neutron(-0.4,-0.4)
\neutron(0.4,0.4)
\proton(-0.4,-0.4)
\proton(0.4,0.4)
\proton(-0.4,-0.4)
\proton(0.4,-0.4)
\neutron(-0.4,0.4)
\neutron(-0.4,0.4)
\neutron(0.4,-0.4)
\proton(-0.4,0.4)
%%orbits
\orbit(0,-\pos,0cm)
\orbit(195,\pos,0cm)
\orbit(120,-\pos,0cm)
\orbit(65,\pos,0cm)
\orbit(270,\pos,0cm)
\orbit(330,-\pos,0cm)
\end{tikzpicture}
}

\end{document}
\end{filecontents*}
%
\immediate\write18{pdflatex atom}
%
% convert to GIF animation
\immediate\write18{convert -delay 10 -loop 0 -density 200 -alpha remove atom.pdf atom.gif}
%
% convert to PNG
\makeatletter
\immediate\write18{convert -density 200 -alpha on atom.pdf atom-\@percentchar02d.png}
\makeatother
%
\usepackage{animate}
\begin{document}
\begin{preview}
%\animategraphics[controls,autoplay,loop,scale=<integer>]{<frame rate>}{<PDF filename without extension>}{<left blank>}{<left blank>}
\animategraphics[controls,autoplay,loop,scale=1]{8}{atom}{}{}
\end{preview}
\end{document}

enter image description here

Update - 2

\documentclass[preview,border={10pt 0pt 10pt 10pt}]{standalone}
\usepackage{filecontents}
\begin{filecontents*}{atom.tex}
\documentclass[tikz,border=20pt]{standalone}
\usepackage{tikz,graphicx}
\usetikzlibrary{decorations.markings,calc}

\definecolor{myyellow}{RGB}{254,241,24}
\definecolor{myorange}{RGB}{234,125,1}

\def\proton(#1,#2){%
    \fill[shade=ball,ball color=myyellow] ({rnd*#1},{rnd*#2}) circle (10pt) node {\texttt{+}};
}
\def\neutron(#1,#2){%
    \fill[shade=ball,ball color=myorange] ({rnd*#1},{rnd*#2}) circle (10pt);
}
\def\electron{%
    \fill[shade=ball,ball color=gray!30] (0,0) circle (5pt);
    \node at (0,0) {\texttt{-}};
}
\def\onesorbit(#1,#2,#3){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,pre=moveto,pre length=#3,
  mark=at position #2 with {\electron},
}]
  (0,0) ellipse (1 and 2);
}
\def\twosorbit(#1,#2,#3){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,pre=moveto,pre length=#3,
  mark=at position #2 with {\electron},
}]
  (0,0) ellipse (2 and 3.5);
}
\def\twoporbit(#1,#2,#3){%
  \draw[
  color=violet,
  rotate=#1,
  postaction=decorate,
  decoration={markings,pre=moveto,pre length=#3,
  mark=at position #2 with {\electron},
}]
  (0,0) ellipse (3 and 5);
}
\begin{document}
\foreach \pos in {0,0.08,0.16,...,0.96}{%
\begin{tikzpicture}
%%Nucleons
\neutron(0.4,0.4)
\proton(0.4,-0.4)
\neutron(-0.4,-0.4)
\neutron(0.4,0.4)
\proton(-0.4,-0.4)
\proton(0.4,0.4)
\proton(-0.4,-0.4)
\proton(0.4,-0.4)
\neutron(-0.4,0.4)
\neutron(-0.4,0.4)
\neutron(0.4,-0.4)
\proton(-0.4,0.4)
%%orbits
\onesorbit(10,\pos,0cm)
\twosorbit(160,\pos,0cm)
\onesorbit(110,-\pos,0cm)
\twoporbit(30,\pos,0cm)
\twoporbit(310,-\pos,0cm)
\twosorbit(60,-\pos,0cm)
\end{tikzpicture}
}
\end{document}
\end{filecontents*}
%
\immediate\write18{pdflatex atom}

% convert to GIF animation
\immediate\write18{convert -delay 10 -loop 0 -density 200 -alpha remove atom.pdf atom.gif}
%
% convert to PNG
\makeatletter
\immediate\write18{convert -density 200 -alpha on atom.pdf atom-\@percentchar02d.png}
\makeatother

\usepackage{animate}
\begin{document}
\begin{preview}
%\animategraphics[controls,autoplay,loop,scale=<integer>]{<frame rate>}{<PDF filename without extension>}{<left blank>}{<left blank>}
\animategraphics[controls,autoplay,loop,scale=1]{15}{atom}{}{}
\end{preview}
\end{document}

enter image description here

This is an attempt to show orbits in different planes using ellipse

5
  • 2
    Upvoted because of your second sentence. ;-)
    – Speravir
    Commented Sep 21, 2012 at 0:43
  • 1
    Unfortunately, although you've made the nucleus stable, you've also changed the electron orbitals from circular to elliptical so the diagram no longer illustrates the Bohr model of the atom in having 2 electrons in the (filled) s-shell and and 4 in the (partially filled) d-shell. :-)
    – StarNamer
    Commented Sep 21, 2012 at 1:11
  • 316 KiB should be negligible for most of us. Commented Sep 25, 2012 at 16:08
  • 1
    @GarbageCollector: I dedicate this animation to you. :)
    – user11232
    Commented Sep 25, 2012 at 16:12
  • 1
    The complete code up to generating MP4 can be seen in my answer How to create animations and movie in a single pdflatex execution. Commented Sep 25, 2012 at 19:56
24

Just for comparison purpose. The following uses PSTricks.

Still Version:

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\psset{dimen=middle}
\begin{document}
\begin{pspicture}(-2,-2)(2,2)
    % nucleous
    \pscircle(0,0){0.15}
    \rput(0,0){+}
    % first orbit
    \pscircle(0,0){1}
    % first electron on the first orbit
    \pscircle[fillstyle=solid,fillcolor=white](1,0){0.15}
    \rput(1,0){-}
\end{pspicture}
\end{document}

Animated Version:

enter image description here

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\psset{dimen=middle}
\begin{document}
\multido{\i=0+10}{36}{%
\begin{pspicture}(-2,-2)(2,2)
    % nucleous
    \pscircle(0,0){0.15}
    \rput(0,0){+}
    % first orbit
    \pscircle(0,0){1}
    % first electron on the first orbit
    \pscircle[fillstyle=solid,fillcolor=white](1;\i){0.15}
    \rput(1;\i){-}
\end{pspicture}}
\end{document}

Animated version in PDF format (as opposed to GIF format):

% this filename is main.tex
% compile it with pdflatex -shell-escape main

\documentclass[preview]{standalone}

\usepackage{filecontents}
\begin{filecontents*}{atom.tex}
\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\psset{dimen=middle}
\begin{document}
\multido{\i=0+10}{36}{%
\begin{pspicture}(-2,-2)(2,2)
 % nucleous
 \pscircle(0,0){0.15}
 \rput(0,0){+}
 % first orbit
 \pscircle(0,0){1}
 % first electron on the first orbit
 \pscircle[fillstyle=solid,fillcolor=white](1;\i){0.15}
 \rput(1;\i){-}
\end{pspicture}}
\end{document}
\end{filecontents*}

\usepackage{animate}

\immediate\write18{latex atom}
\immediate\write18{dvips atom}
\immediate\write18{ps2pdf atom.ps}

\begin{document}
%\animategraphics[<options>]{<frame per second>}{<pdf filename without extension>}{}{}
\animategraphics[controls]{5}{atom}{}{}
\end{document}
5
  • 1
    +1 I love getting these animated answers here and there on the site, they're fun. I'm completely ignorant of PSTricks, so forgive me if that's a basic question: Do the animations run in the PDF as well (possibly with some JavaScript magic)?
    – doncherry
    Commented Sep 21, 2012 at 4:28
  • 1
    \animategraphics has some options. You can try controls, loop, scale=<floating number>, etc. Commented Sep 21, 2012 at 4:50
  • Sweet, thanks! :) If I wasn't yearning for breaking the 10k barrier right now, I'd give you a bounty. Might do it later.
    – doncherry
    Commented Sep 21, 2012 at 5:00
  • I should use $-$ rather than -. Commented Sep 21, 2012 at 11:31
  • @doncherry: when will you offer a bounty for me? :-) Commented Apr 25, 2013 at 11:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .