% --------------------------------------------------------------------------
% the BOHR package
% 
%   simple atom representation according to the Bohr model
% 
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://bitbucket.org/cgnieder/bohr/
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2012 Clemens Niederberger
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
% 
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
% The bohr package consists of the files
%  - bohr.sty
%  - bohr_en.tex, bohr_en.pdf
%  - bohr_elements_english.def, bohr_elements_german.def
%  - README
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
\def\@bohr@date{2012/09/26}
\def\@bohr@version{v0.2b}
\def\@bohr@description{simple atom representation according to the Bohr model}

\ProvidesPackage{bohr}[\@bohr@date\space \@bohr@version\space \@bohr@description]
\RequirePackage{tikz,etoolbox,pgfopts}

% --------------------------------------------------------------------------
% message handling
\def\@bohr@create@message#1{%
  \ifstrequal{#1}{Error}
    {%
      \lowercase{\csdef{@bohr@#1}}##1##2{%
        \csuse{Package#1}{bohr}{##1}{##2}}%
    }{%
      \lowercase{\csdef{@bohr@#1}}##1{%
        \csuse{Package#1}{bohr}{##1}}%
    }}
\@bohr@create@message{Error}
\@bohr@create@message{Warning}
\@bohr@create@message{WarningNoLine}
\@bohr@create@message{Info}

% --------------------------------------------------------------------------
% the \bohr command
%   optional #1: number of shells
%   #2: number of electrons
%   #3: atom name
\newrobustcmd*\bohr[3][]{\@bohr{#1}{#2}{#3}}

\def\@bohr#1#2#3{%
  \ifblank{#2}% electron number given ?
    {% no
      \ifboolexpr{ bool {bohr@insert@number} and test {\ifblank{#3}} }
        {%
          \@bohr@error{I can't insert the electron number.}
            {I can't insert the electron number. You haven't specified the
            element.}%
        }{%
          \ifboolexpr
            {
              bool {bohr@insert@number} and not
              test {\lowercase{\ifcsvoid{@bohr@atom@number@#3}}}
            }
            {%
              \lowercase{%
                \def\@bohr@electron@current@number{\csuse{@bohr@atom@number@#3}}}%
            }{%
              \@bohr@error{You must specify an electron number, possibly 0.}
                {You must specify an electron number, possibly 0.}%
            }%
        }%
    }{% yes
      \ifnum#2<0\relax
        \@bohr@error{The electron number cannot be negative!}
          {The electron number cannot be negative!}%
      \else
        \def\@bohr@electron@current@number{#2}%
      \fi
    }%
  \ifblank{#1}
    {\@bohr@get@shell@num{\@bohr@electron@current@number}}
    {
      \@bohr@get@shell@num{\@bohr@electron@current@number}%
      \ifnum#1<\@bohr@shell@num
        \@bohr@warning{The shell number you provided (#1) is too small for the
          electron number you provided (\@bohr@electron@current@number)! I'll
          use \@bohr@shell@num\space shells.}%
      \else
        \ifnum#1>7\relax
          \@bohr@warning{I know only of 7 electron shells. You gave me #1 so I'll
            be using 7 instead.}
          \def\@bohr@shell@num{7}%
        \else
          \def\@bohr@shell@num{#1}%
        \fi
      \fi
    }%
  \tikzpicture[baseline=(nucleus.base)]
    \expandafter\node\expandafter[\@bohr@name@options]
      (nucleus) at (0,0) {\@bohr@insert@symbol{\@bohr@electron@current@number}{#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{\@bohr@electron@current@number}
  \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
            \ifnum#1<87\relax
              \def\@bohr@shell@num{6}%
            \else
              \ifnum#1<110\relax
                \def\@bohr@shell@num{7}%
              \else
                \def\@bohr@shell@num{112}%
                \@bohr@warning{I only know atoms up to 112 (Copernicium). You
                  gave me #1 so I am using 112 instead.}
              \fi
            \fi
          \fi
        \fi
      \fi
    \fi
  \fi
}

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

\def\@bohr@draw@electrons#1{%
  \ifnum#1<1\relax\else
    \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{1}{#1-2}{45}{2}%
      \else
        \ifnum#1<19\relax
          \@bohr@distribute@electrons{1}{2}{180}{1}%
          \@bohr@distribute@electrons{1}{8}{45}{2}%
          \@bohr@distribute@electrons{1}{#1-10}{45}{3}%
        \else
          \ifnum#1<37\relax
            \@bohr@distribute@electrons{1}{2}{180}{1}%
            \@bohr@distribute@electrons{1}{8}{45}{2}%
            \@bohr@distribute@electrons{1}{8}{45}{3}%
            \@bohr@distribute@electrons{1}{#1-18}{20}{4}%
          \else
            \ifnum#1<55\relax
              \@bohr@distribute@electrons{1}{2}{180}{1}%
              \@bohr@distribute@electrons{1}{8}{45}{2}%
              \@bohr@distribute@electrons{1}{8}{45}{3}%
              \@bohr@distribute@electrons{1}{18}{20}{4}%
              \@bohr@distribute@electrons{1}{#1-36}{20}{5}%
            \else
              \ifnum#1<87\relax
                \@bohr@distribute@electrons{1}{2}{180}{1}%
                \@bohr@distribute@electrons{1}{8}{45}{2}%
                \@bohr@distribute@electrons{1}{8}{45}{3}%
                \@bohr@distribute@electrons{1}{18}{20}{4}%
                \@bohr@distribute@electrons{1}{18}{20}{5}%
                \@bohr@distribute@electrons{1}{#1-54}{11.25}{6}%
              \else
                \ifnum#1<113\relax
                  \@bohr@distribute@electrons{1}{2}{180}{1}%
                  \@bohr@distribute@electrons{1}{8}{45}{2}%
                  \@bohr@distribute@electrons{1}{8}{45}{3}%
                  \@bohr@distribute@electrons{1}{18}{20}{4}%
                  \@bohr@distribute@electrons{1}{18}{20}{5}%
                  \@bohr@distribute@electrons{1}{32}{11.25}{6}%
                  \@bohr@distribute@electrons{1}{#1-86}{11.25}{7}%
                \fi
              \fi
            \fi
          \fi
        \fi
      \fi
    \fi
  \fi
}

% --------------------------------------------------------------------------
% atomic numbers and element symbols and names
\def\@bohr@define@atom@symbol#1#2{%
  \csdef{@bohr@atom@symbol@num@\romannumeral#1}{#2}%
  \lowercase{\csdef{@bohr@atom@number@#2}}{#1}}
\def\@bohr@define@atom@name#1#2#3{%
  \csdef{@bohr@atom@name@\romannumeral#1}{#2}%
  \lowercase{\csdef{@bohr@atom@name@num@#3}}{#1}}

% #1: optional name (umlauts...)
% #2: atomic number
% #3: element name
\newrobustcmd*\DeclareAtomName[3][]{%
  \ifblank{#1}
    {\@bohr@define@atom@name{#2}{#3}{#3}}
    {\@bohr@define@atom@name{#2}{#3}{#1}}}
% #1: atomic number
% #2: element symbol
\newrobustcmd*\DeclareAtomSymbol[2]{%
  \@bohr@define@atom@symbol{#1}{#2}}

\def\@bohr@get@atom@symbol#1{%
  \csuse{@bohr@atom@symbol@num@\romannumeral#1}}
\def\@bohr@get@atom@number#1{%
  \lowercase{\csuse{@bohr@atom@number@#1}}}
\def\@bohr@get@atom@name#1{%
  \csuse{@bohr@atom@name@\romannumeral#1}}

\def\@bohr@element@symbol#1{%
  \lowercase{\ifcsdef{@bohr@atom@name@num@#1}}
    {\lowercase{\@bohr@get@atom@symbol{\csuse{@bohr@atom@name@num@#1}}}}
    {\@bohr@get@atom@symbol{#1}}}

\def\@bohr@atomic@number#1{%
  \lowercase{\ifcsdef{@bohr@atom@number@#1}}
    {\@bohr@get@atom@number{#1}}
    {\lowercase{\csuse{@bohr@atom@name@num@#1}}}}

\def\@bohr@elemt@symbol#1{%
  \if!\ifnum9<1#1!\@bohr@get@atom@name{#1}\fi
  \else
    \lowercase{\@bohr@get@atom@name{\csuse{@bohr@atom@number@#1}}}%
  \fi}

\newrobustcmd*\elementsymbol[1]{\@bohr@element@symbol{#1}}
\newrobustcmd*\atomicnumber[1]{\@bohr@atomic@number{#1}}
\newrobustcmd*\elementname[1]{\@bohr@elemt@symbol{#1}}
\ifdef\Z{}{\let\Z\atomicnumber}

\DeclareAtomSymbol{1}{H}
\DeclareAtomSymbol{2}{He}
\DeclareAtomSymbol{3}{Li}
\DeclareAtomSymbol{4}{Be}
\DeclareAtomSymbol{5}{B}
\DeclareAtomSymbol{6}{C}
\DeclareAtomSymbol{7}{N}
\DeclareAtomSymbol{8}{O}
\DeclareAtomSymbol{9}{F}
\DeclareAtomSymbol{10}{Ne}
\DeclareAtomSymbol{11}{Na}
\DeclareAtomSymbol{12}{Mg}
\DeclareAtomSymbol{13}{Al}
\DeclareAtomSymbol{14}{Si}
\DeclareAtomSymbol{15}{P}
\DeclareAtomSymbol{16}{S}
\DeclareAtomSymbol{17}{Cl}
\DeclareAtomSymbol{18}{Ar}
\DeclareAtomSymbol{19}{K}
\DeclareAtomSymbol{20}{Ca}
\DeclareAtomSymbol{21}{Sc}
\DeclareAtomSymbol{22}{Ti}
\DeclareAtomSymbol{23}{V}
\DeclareAtomSymbol{24}{Cr}
\DeclareAtomSymbol{25}{Mn}
\DeclareAtomSymbol{26}{Fe}
\DeclareAtomSymbol{27}{Co}
\DeclareAtomSymbol{28}{Ni}
\DeclareAtomSymbol{29}{Cu}
\DeclareAtomSymbol{30}{Zn}
\DeclareAtomSymbol{31}{Ga}
\DeclareAtomSymbol{32}{Ge}
\DeclareAtomSymbol{33}{As}
\DeclareAtomSymbol{34}{Se}
\DeclareAtomSymbol{35}{Br}
\DeclareAtomSymbol{36}{Kr}
\DeclareAtomSymbol{37}{Rb}
\DeclareAtomSymbol{38}{Sr}
\DeclareAtomSymbol{39}{Y}
\DeclareAtomSymbol{40}{Zr}
\DeclareAtomSymbol{41}{Nb}
\DeclareAtomSymbol{42}{Mo}
\DeclareAtomSymbol{43}{Tc}
\DeclareAtomSymbol{44}{Ru}
\DeclareAtomSymbol{45}{Rh}
\DeclareAtomSymbol{46}{Pd}
\DeclareAtomSymbol{47}{Ag}
\DeclareAtomSymbol{48}{Cd}
\DeclareAtomSymbol{49}{In}
\DeclareAtomSymbol{50}{Sn}
\DeclareAtomSymbol{51}{Sb}
\DeclareAtomSymbol{52}{Te}
\DeclareAtomSymbol{53}{I}
\DeclareAtomSymbol{54}{Xe}
\DeclareAtomSymbol{55}{Cs}
\DeclareAtomSymbol{56}{Ba}
\DeclareAtomSymbol{57}{La}
\DeclareAtomSymbol{58}{Ce}
\DeclareAtomSymbol{59}{Pr}
\DeclareAtomSymbol{60}{Nd}
\DeclareAtomSymbol{61}{Pm}
\DeclareAtomSymbol{62}{Sm}
\DeclareAtomSymbol{63}{Eu}
\DeclareAtomSymbol{64}{Gd}
\DeclareAtomSymbol{65}{Tb}
\DeclareAtomSymbol{66}{Dy}
\DeclareAtomSymbol{67}{Ho}
\DeclareAtomSymbol{68}{Er}
\DeclareAtomSymbol{69}{Tm}
\DeclareAtomSymbol{70}{Yb}
\DeclareAtomSymbol{71}{Lu}
\DeclareAtomSymbol{72}{Hf}
\DeclareAtomSymbol{73}{Ta}
\DeclareAtomSymbol{74}{W}
\DeclareAtomSymbol{75}{Rh}
\DeclareAtomSymbol{76}{Os}
\DeclareAtomSymbol{77}{Ir}
\DeclareAtomSymbol{78}{Pt}
\DeclareAtomSymbol{79}{Au}
\DeclareAtomSymbol{80}{Hg}
\DeclareAtomSymbol{81}{Tl}
\DeclareAtomSymbol{82}{Pb}
\DeclareAtomSymbol{83}{Bi}
\DeclareAtomSymbol{84}{Po}
\DeclareAtomSymbol{85}{At}
\DeclareAtomSymbol{86}{Rn}
\DeclareAtomSymbol{87}{Fr}
\DeclareAtomSymbol{88}{Ra}
\DeclareAtomSymbol{89}{Ac}
\DeclareAtomSymbol{90}{Th}
\DeclareAtomSymbol{91}{Pa}
\DeclareAtomSymbol{92}{U}
\DeclareAtomSymbol{93}{Np}
\DeclareAtomSymbol{94}{Pu}
\DeclareAtomSymbol{95}{Am}
\DeclareAtomSymbol{96}{Cm}
\DeclareAtomSymbol{97}{Bk}
\DeclareAtomSymbol{98}{Cf}
\DeclareAtomSymbol{99}{Es}
\DeclareAtomSymbol{100}{Fm}
\DeclareAtomSymbol{101}{Md}
\DeclareAtomSymbol{102}{No}
\DeclareAtomSymbol{103}{Lr}
\DeclareAtomSymbol{104}{Rf}
\DeclareAtomSymbol{105}{Db}
\DeclareAtomSymbol{106}{Sg}
\DeclareAtomSymbol{107}{Bh}
\DeclareAtomSymbol{108}{Hs}
\DeclareAtomSymbol{109}{Mt}
\DeclareAtomSymbol{110}{Ds}
\DeclareAtomSymbol{111}{Rg}
\DeclareAtomSymbol{112}{Cn}

% element names are defined in bohr_elements_english.def or
% bohr_elements_german.def, respectively. Now we need to decide
% which ones we want
\AfterEndPreamble{
\ifdef\bbl@afterfi{}{\long\def\bbl@afterfi#1{\fi#1}}
\ifboolexpr
  {
    test {\iflanguage{german}} or
    test {\iflanguage{ngerman}}
  }
  {\booltrue{bohr@german}}{}
\ifbool{bohr@german}
  {\input{bohr_elements_german.def}}
  {\input{bohr_elements_english.def}}
}


% --------------------------------------------------------------------------
% options
\def\@bohr@name@options{}
\def\@bohr@write@atom#1{#1}
\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}

\newbool{bohr@insert@symbol}
\newbool{bohr@insert@number}
\newbool{bohr@german}

\def\@bohr@insert@symbol#1#2{%
  \ifbool{bohr@insert@symbol}
    {\ifblank{#2}{\@bohr@get@atom@symbol{#1}}{\@bohr@write@atom{#2}}}
    {\@bohr@write@atom{#2}}}

\pgfkeys{
  bohr/.cd,
    insert-symbol/.is if       = bohr@insert@symbol ,
    insert-number/.is if       = bohr@insert@number ,
    insert-missing/.is choice,
    insert-missing/true/.code  =
      \booltrue{bohr@insert@symbol}\booltrue{bohr@insert@number} ,
    insert-missing/false/.code =
      \boolfalse{bohr@insert@symbol}\boolfalse{bohr@insert@number} ,
    insert-missing/.default    = true ,
    atom-style/.code           = \def\@bohr@write@atom{#1} ,
    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} ,
    german/.is if              = bohr@german ,
    ngerman/.is if             = bohr@german
}

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

\ProcessPgfOptions*
\endinput

% HISTORY
2012/09/21 v0.1a - first version on bitbucket
2012/09/22 v0.2  - added compatibility up to atomic number 112
                 - added the commands \elementname and \elementsymbol with
                   language support German and English
                 - improved error checking