In chemistry, a Frost circle is a quick method to estimate the relative energy levels of the pi molecular orbitals in a cyclic compound and then based on electron placement judge its aromaticicity. I'm looking for a way to create these in LaTeX, preferably using the functionality of packages like chemfig and tikzorbital, but I will settle for a tikz only solution.

A Frost circle is created by inscribing the polygon for the cyclic compound (for example a regular hexagon for benzene) inside a circle with one vertex of the polygon oriented downward. Each location where a vertex of the polygon touches the circle, this is a molecular orbital that can have up to two electrons in it (represented by fishhook arrows). The orbitals below the horizontal line that bisects the circle are bonding orbitals. Those above are antibonding orbitals. Any orbitals on that lay on the line are nonbonding orbitals. Electrons are placed into the orbitals by some rules.

  • The aufbau principle: Orbitals are filled in order of increasing energy.
  • The Pauli exclusion principle: Each orbital can hold only two electrons and their spins (arrow directions) must be opposite.
  • Hund's rule: If two orbitals have the same energy, one electron does into each before either gets its second electron.

Here is a longer description of the method and its application.

My ideal solution is new command that takes the ring size and number of electrons as an input and builds Frost circles like the following examples by:

  • Drawing the circle
  • Inscribing the regular polygon with number of sides equal to ring size (up to 10)
  • Drawing horizontal line segments at the vertices of the polygon for the molecular orbitals
  • Drawing the vertical energy axis
  • Drawing the dashed line for the bonding/antibonding division
  • Populating the number of electrons by the rules above

Here are some examples: benzene (ring size = 6, electrons = 6)

frost circle for benzene

cyclopentadienyl cation (ring size = 5, electrons = 4)

frost circle with 5 atoms and 4 electrons

cyclooctatetraene (ring size = 8, electrons = 8)

enter image description here

  • Excuse me very much for this comment. But do you have seen these images?
    – Sebastiano
    Commented Oct 8, 2020 at 15:12
  • @Sebastiano - I made these images in chemistry drawing software, but each one took about 10 minutes. Because they contain a mixture of chemical structure and nonstructural elements, I cannot export them as vector graphics. If I could do that, I would just import them into my latex document that way. I am working on a document where I may want to draw dozens of these.
    – Ben Norris
    Commented Oct 8, 2020 at 16:10
  • 3
    The images are crisp and clear even without svg format, you can just store png images to a large enough scale so that when they are zoomed-out when included in the PDF, they become even smoother.
    – AboAmmar
    Commented Oct 8, 2020 at 16:32
  • 1
    @AboAmmar - I understand that, but the time commitment for making one is large for very repetitive work. I would like to have a macro that automates it since I plan to make dozens of these.
    – Ben Norris
    Commented Oct 8, 2020 at 16:34
  • 1
    @BenNorris You could to draw your images using Mathcha editor. mathcha.io/editor
    – Sebastiano
    Commented Oct 8, 2020 at 17:09

3 Answers 3


Here is a fully automated solution. The calls for your three examples are


There is an optional argument for radius size. Default is 1cm. So frost[2cm]{6}{6} would have a radius of 2cm.

enter image description here

Note: This only works (at the moment) if there are an even number of electrons.



\tikzset% Define decorations
   {updown/.style={postaction=decorate, decoration={markings, mark=at position .5 with
   {\draw[line join=round] (-2pt,-\arrlen)--++(0pt,2*\arrlen)--(-4pt,1pt);
   \draw[line join=round] (2pt,\arrlen)--++(0pt,-2*\arrlen)--(4pt,-1pt);
   }}},% 2 arrows
   uparr/.style={postaction=decorate, decoration={markings, mark=at position .5 with
   {\draw[line join=round] (0pt,-\arrlen)--++(0pt,2*\arrlen)--(-2pt,1pt);
   }}},% 1 arrow, right side
   dnarr/.style={postaction=decorate, decoration={markings, mark=at position .5 with
   {\draw[line join=round] (0pt,\arrlen)--++(0pt,-2*\arrlen)--(2pt,-1pt);
   }}}% 1 arrow left side (points down since lines will be drawn right to left)

\newcommand{\orblen}{.8}% length of horizontal segments as a percentage of main radius
\newcommand{\arrlen}{.25cm}% half length of each arrow

\newcommand{\frost}[3][1cm]% optional argument is circle radius, #2=edges, #3=electrons
{\begin{tikzpicture}[line width=1pt]
\draw(0,0)circle[radius=#1];% main circle
\ifthenelse{#3 = 0}{\draw(-.5*#1*\orblen,-#1)--(.5*#1*\orblen,-#1);}% draw bottom line segment...
    {\draw[updown](-.5*#1*\orblen,-#1)--(.5*#1*\orblen,-#1);}% ...with arrows if >0 electrons
\foreach \k [evaluate=\k as \r using .5*#2+1,% point right if k<r, point left if k>r, top if k=r
    evaluate=\k as \t using (\k-1)*360/#2-90,% angles of polygon vertices. k=1 is bottom.
    evaluate=\k as \n using -4*\k+6+#3,% who gets 2 electrons (right)?
    evaluate=\k as \m using -4*(#2+2-\k)+6+#3,% who gets 2 electrons (left)?
    evaluate=\k as \j using 2*#2] in {1,...,#2}% electrons for top if #3=2*#2
    \ifthenelse{\k>1}% already did bottom line.
    {\ifthenelse{\lengthtest{\k pt < \r pt}}% right side
        {\ifthenelse{3 < \n}{\draw[updown](\t:#1)--+(#1*\orblen,0);}% 2 arrows
        {\ifthenelse{1 < \n}{\draw[uparr](\t:#1)--+(#1*\orblen,0);}% 1 arrow
        {\draw(\t:#1)--+(#1*\orblen,0);}}}% no arrows
    {\ifthenelse{\lengthtest{\k pt > \r pt}}% left side
        {\ifthenelse{3 < \m}{\draw[updown](\t:#1)--+(-#1*\orblen,0);}% 2arrows
        {\ifthenelse{1 < \m}{\draw[dnarr](\t:#1)--+(-#1*\orblen,0);}% 1 arrow
        {\draw(\t:#1)--+(-#1*\orblen,0);}}}%no arrows
        {\ifthenelse{#3 = \j}{\draw[updown](-.5*#1*\orblen,#1)--(.5*#1*\orblen,#1);}% 2 arrows on top
        {\draw(-.5*#1*\orblen,#1)--(.5*#1*\orblen,#1);}}} % no arrows on top
    }{} % do nothing if k=1 (bottom)





  • Very good also your answer.
    – Sebastiano
    Commented Oct 9, 2020 at 22:02
  • Excellent! This works beautifully.
    – Ben Norris
    Commented Oct 10, 2020 at 20:27

Honestly, it's taken some effort, but your figure was intriguing and it allowed me to learn new things1 so, it's all good.

Basically I've created a \newcommand, name \Frostcircle, which has 2 arguments, options and the electrons.

Currently, the [options] are:

  • radius = the radius of the circle, please note that at the moment the surrounding graphics do not adjust if you make it too big. I might work on it in the future. It only takes a number (in cm) at the moment, using lengths breaks it, I'm not sure why yet. Suggestions are welcome.
  • ring size = this refers to the number of sides of the polygon. Number of sides from 5 to 10 have been tested. As you might expect, it takes a number as argument
  • frost label = this is the label at the top, default is empty. Make sure to surround the text with curly braces, e.g. frost label={My label here}

The other argument are the electrons, the easiest way I could find is to set them in a counterclockwise fashion, starting from the top, as in this figure:

how the command works

It takes values 0, 1, and 2: in order, no electron, one electron, two electrons. You can supply it as a list so giving {0,0,2,2,2,0} would give your benzene frost circle. It might sound counterintuitive but it's actually simple once you give it a try.

If the number of elements in the list you provide are less than the ring size, you will get an error and the code will not compile. If you want no electron, just type 0 to solve this.


The direction of the "arrow" for the electron is inverted on the other side, not sure if this is important for your graphs. I can look into it another day if it's important. FIXED

Also I added the same packages as in Sebastiano's answer to get the math font, but they are not needed for the command to work.


frost circle examples




            mark=at position .5 with
                \draw[-{Straight Barb[left,angle=60:2pt 3]}] (0,-6pt) --(0,6pt);
                \draw[-{Straight Barb[left,angle=60:2pt 3]}] (-1pt,-6pt) -- (-1pt,6pt);
                \draw[{Straight Barb[left,angle=60:2pt 3]}-] (1pt,-6pt) -- (1pt,6pt);
    mlbl/.style={anchor=south, align=center, midway, sloped},

\pgfkeys{/tikz/.cd,% to set the path
    radius/.initial=.8, % initial value
    radius/.get=\circleradius, % to get the value from a macro
    radius/.store in=\circleradius, % to store the value into a macro
    ring size/.initial=5,
    ring size/.get=\numbersides,
    ring size/.store in=\numbersides,
    frost label/.initial=,
    frost label/.get=\frostlabel,
    frost label/.store in=\frostlabel,

    \tikzset{radius=.8,ring size=5,frost label=,#1}
    \begin{tikzpicture}[line width=1pt]
    \draw[-{Stealth[scale=1.5]}] (0,0) -- (0,3cm) 
    node[mlbl] {Energy}
    node[anchor=north west, xshift=2mm] {\frostlabel};
\draw[dotted, shorten >=-1cm] (.5,1) -- (4,1)
    node[anchor=south west] {antibonding}
    node[anchor=north west] {bonding};
\draw (2,1) circle (\circleradius);
    regular polygon, 
    regular polygon sides=\numbersides,
    minimum size=\circleradius*2 cm, 
    outer sep=0pt
] at (2,1) (FrostCircle) {};

\foreach \polycorner [count=\findex starting from 0] in {1,...,\numbersides}{%
        \draw[electron=\Findex] (FrostCircle.corner \polycorner)++(-.8,0) --++ (1.6,0);
        \draw[electron=\Findex] (FrostCircle.corner \polycorner)++(-.8,0) --++ (1.6,0);
        \draw[electron=\Findex] (FrostCircle.corner \polycorner)++ (-.8,0) -- (FrostCircle.corner \polycorner);
        \draw[electron=\Findex] (FrostCircle.corner \polycorner) --++ (.8,0);


    ring size=6, 
    frost label={benzene (ring size = 6, electrons = 6)}


    ring size=5, 
    frost label={cyclopentadienyl cation (ring size = 5, electrons = 4)}


    ring size=8, 
    frost label={cyclooctatetraene (ring size = 8, electrons = 8)}


1: The pgfkeys.

  • 1
    Thank you very much for the citation of my name :-) ; for my humble opinion it not was important. Your different codes are perfect!!!! +1
    – Sebastiano
    Commented Oct 9, 2020 at 19:48
  • This is great! Generally in the ground state, unpaired electrons (arrows) would have the same spin (same direction), so SandyG's solution matches my needs a little better.
    – Ben Norris
    Commented Oct 10, 2020 at 20:32
  • @BenNorris interesting. I'll take a look at that later. It shouldn't be hard to achieve.
    – Alenanno
    Commented Oct 10, 2020 at 20:35
  • @BenNorris I just wanted to let you know, I fixed the direction. It was rather easy, not sure why I didn't think of it sooner.
    – Alenanno
    Commented Oct 10, 2020 at 21:19

I have done with Mathcha the first example. For my humble opinion it seem very similar...but there is a latin maxime: "de gustibus non disputandum est".



\tikzset{every picture/.style={line width=0.75pt}} %set default line width to 0.75pt        

%uncomment if require: \path (0,300); %set diagram left start at 0, and has height of 300

%Shape: Regular Polygon [id:dp9024119328579219] 
\draw  [line width=1.5]  (203,184) -- (161.86,160.25) -- (161.86,112.75) -- (203,89) -- (244.14,112.75) -- (244.14,160.25) -- cycle ;
%Shape: Circle [id:dp3742321630799761] 
\draw  [line width=1.5]  (155.5,136.5) .. controls (155.5,110.27) and (176.77,89) .. (203,89) .. controls (229.23,89) and (250.5,110.27) .. (250.5,136.5) .. controls (250.5,162.73) and (229.23,184) .. (203,184) .. controls (176.77,184) and (155.5,162.73) .. (155.5,136.5) -- cycle ;
%Straight Lines [id:da6431705906977057] 
\draw [line width=1.5]    (101,185) -- (101,31.71) ;
\draw [shift={(101,27.71)}, rotate = 450] [fill={rgb, 255:red, 0; green, 0; blue, 0 }  ][line width=0.08]  [draw opacity=0] (13.4,-6.43) -- (0,0) -- (13.4,6.44) -- (8.9,0) -- cycle    ;
%Straight Lines [id:da03628267423150655] 
\draw [line width=1.5]    (176.75,89) -- (229.25,89) ;
%Straight Lines [id:da6999074691962319] 
\draw [line width=1.5]    (244.14,112.75) -- (285.5,112.75) ;
%Straight Lines [id:da6267867712352968] 
\draw [line width=1.5]    (120.5,112.75) -- (161.86,112.75) ;
%Straight Lines [id:da4603867099439829] 
\draw [line width=1.5]    (244.14,160.25) -- (285.5,160.25) ;
%Straight Lines [id:da018369347304083128] 
\draw [line width=1.5]    (120.5,160.25) -- (161.86,160.25) ;
%Straight Lines [id:da7545009709936943] 
\draw [line width=1.5]    (176.75,184) -- (229.25,184) ;
%Straight Lines [id:da42526907269791137] 
\draw [line width=1.5]  [dash pattern={on 1.69pt off 2.76pt}]  (120.5,136.5) -- (346.5,136.5) ;

% Text Node
\draw (126,149.4) node [anchor=north west][inner sep=0.75pt]  [font=\large]  {$\bm{\upharpoonleft }$};
% Text Node
\draw (249,149.4) node [anchor=north west][inner sep=0.75pt]  [font=\large]  {$\bm{\upharpoonleft }$};
% Text Node
\draw (195,173.4) node [anchor=north west][inner sep=0.75pt]  [font=\large]  {$\bm{\upharpoonleft }$};
% Text Node
\draw (130,149.4) node [anchor=north west][inner sep=0.75pt]  [font=\large]  {$\bm{\downharpoonright }$};
% Text Node
\draw (253,149.4) node [anchor=north west][inner sep=0.75pt]  [font=\large]  {$\bm{\downharpoonright }$};
% Text Node
\draw (200,173.4) node [anchor=north west][inner sep=0.75pt]  [font=\large]  {$\bm{\downharpoonright }$};
% Text Node
\draw (74,149) node [anchor=north west][inner sep=0.75pt]  [font=\large,rotate=-270] [align=left] {Energy};
% Text Node
\draw (288,103) node [anchor=north west][inner sep=0.75pt]  [font=\large] [align=left] {Antibonding};
% Text Node
\draw (288,150) node [anchor=north west][inner sep=0.75pt]  [font=\large] [align=left] {Bonding};
% Text Node
\draw (120,36) node [anchor=north west][inner sep=0.75pt]   [align=left] {\large benzene (6 atoms, 6 electrons)};


enter image description here

You must log in to answer this question.

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