Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
1  
Can you please upload (or provide a link to) an image of the figure you want? –  Gonzalo Medina Sep 20 '12 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 Sep 20 '12 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 Sep 21 '12 at 15:25
1  
@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 Sep 23 '12 at 15:06
add comment

4 Answers

up vote 28 down vote accepted

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
share|improve this answer
10  
Really nice package; I guess this is what the OP really needs; you chemists are so bohring ;-). –  Gonzalo Medina Sep 21 '12 at 13:55
1  
@GonzaloMedina :) Thanks. I'm (not yet but nearly) a chemistry teacher myself so I'm probably going to make this a “real” package and send it to CTAN... could come in handy some time –  cgnieder Sep 21 '12 at 13:59
    
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 Sep 21 '12 at 14:03
2  
And, @cgnieder - you should really send it in to CTAN - it is very useful! –  Andreas Sep 21 '12 at 14:17
    
@GonzaloMedina: :-D … or: Haha! –  Speravir Sep 21 '12 at 20:15
show 1 more comment

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

share|improve this answer
20  
Oh-Oh! C10 only has a half-life of about 19 seconds! Vote early and fast! :) –  cgnieder Sep 20 '12 at 22:05
4  
Last vote for the day: happy to still have one. –  egreg Sep 20 '12 at 22:08
1  
@cgnieder: Clemens, you are nasty! :-) –  Speravir Sep 20 '12 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 Sep 20 '12 at 23:31
1  
@PauloCereda thank you! I even learnt about C10 and its 19sec. half-life. –  Gonzalo Medina Sep 21 '12 at 0:29
show 6 more comments

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

share|improve this answer
2  
Upvoted because of your second sentence. ;-) –  Speravir Sep 21 '12 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 Sep 21 '12 at 1:11
    
316 KiB should be negligible for most of us. –  Please don't touch Sep 25 '12 at 16:08
1  
@GarbageCollector: I dedicate this animation to you. :) –  Harish Kumar Sep 25 '12 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. –  Please don't touch Sep 25 '12 at 19:56
show 1 more comment

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}
share|improve this answer
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 Sep 21 '12 at 4:28
1  
\animategraphics has some options. You can try controls, loop, scale=<floating number>, etc. –  Please don't touch Sep 21 '12 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 Sep 21 '12 at 5:00
    
I should use $-$ rather than -. –  Please don't touch Sep 21 '12 at 11:31
    
@doncherry: when will you offer a bounty for me? :-) –  Please don't touch Apr 25 '13 at 11:39
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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