This question led to a new package:
bohr
[1]
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?
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}
$6\mathrm{p^+}$
and $6\mathrm{n^0}$
) - cgnieder
:)
- Paulo Cereda
shading=ball
instead shade=ball
for avoiding Package pgfkeys Error: Choice 'ball' unknown in choice key '/tikz/shade'.
errors. - cespon
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}
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
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}
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}
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}
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}
This is an attempt to show orbits in different planes using ellipse
Just for comparison purpose. The following uses PSTricks.
\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}
\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}
% 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}
\animategraphics
has some options. You can try controls
, loop
, scale=<floating number>
, etc. - kiss my armpit
$-$
rather than -
. - kiss my armpit