In the classical way of drawing Feynman diagrams in LaTeX, each diagram becomes a character in a font. That is not a metaphor. Push a feynmf diagram through METAFONT on TeX Live 2024 and it reports "Font metrics written on myfd.tfm" followed by "Output written on myfd.600gf (1 character, 4340 bytes)" — one character. A picture of a scattering process, cast as type, complete with a width table. Figures in the sciences each have their own grammar of drawing, and domain packages take that grammar as their input. This page sorts out the chemistry tools mhchem, chemfig, and XyMTeX; the physics tools tikz-feynman and feynmf; and modiagram for molecular-orbital diagrams — along two axes: what each one makes, and which engine it runs under.
Even within “chemistry and physics figures,” the tool splits sharply by what you want to make. Take the map first, then we look at each in turn.
| Package | Domain | What it makes | Engine / passes |
|---|---|---|---|
mhchem | Chemistry | Formulas and equations set as type (H2O, 2H2+O2 -> 2H2O) | Any engine; one pass |
chemfig | Chemistry | Structural and skeletal formulas, reaction schemes | TikZ-based; pdf, lua, or xe |
xymtex | Chemistry | Structural formulas; rings and skeletons called up as commands | Standard LaTeX, with PostScript and PDF modes |
tikz-feynman | Physics | Feynman diagrams; name the vertices and it places them | Presupposes LuaLaTeX; layout degrades elsewhere |
feynmf / feynmp | Physics | Feynman diagrams; each becomes a font glyph or a MetaPost figure | Two passes; run mf or mpost separately |
modiagram | Chem. and phys. | Molecular-orbital, that is energy-level, diagrams | TikZ-based; one pass |
Chemical formulas and equations in running text: the \ce{} of mhchem
mhchem is not for drawing structures; it is for setting chemical formulas and equations as type. Load it with \usepackage[version=4]{mhchem} and write your expression inside its central command, \ce{...} (chemical equation). Its cleverness is that typing naturally produces correct chemistry: a digit right after an element symbol becomes a subscript (\ce{H2O}), and a number or sign written with ^ becomes a charge superscript (\ce{SO4^2-}). Arrows are typed literally — -> for forward, <=> for equilibrium, <- for reverse — and + is set as an addition of reactants with the right spacing.
\usepackage[version=4]{mhchem}
% ...
\ce{2 H2 + O2 -> 2 H2O}
\ce{CO2 + C ->[\Delta] 2 CO}
\ce{H2O <=> H+ + OH-}
\ce{Ba^2+ + SO4^2- -> BaSO4 v}
\ce{C\bond{-}C}These set, in order: the formation of water (coefficients and subscripts align themselves); heating, where ->[\Delta] puts a condition label above the arrow (write ->[above][below] for two); the autoionisation of water, with a two-way equilibrium arrow; the precipitation of barium sulfate, where the trailing v becomes a downward arrow (an evolved gas is ^); and a single-bond symbol via \bond. \ce{} works in running text and inside $...$ math alike. What it cannot do is draw structures — bond lines and rings are out of scope. For a skeletal picture you want chemfig, next. A later package with the same aim, chemformula, offers the idea through \ch{...}.
Structures in one stroke: chemfig’s bond symbols and angles
chemfig is the standard tool for structural, that is skeletal, formulas of molecules; built on TikZ, it describes a molecule through a mini-language of bonds and branches. Loading is just \usepackage{chemfig}, and the central command is \chemfig{...}. The grammar turns on two things, bond symbols and angles. Bonds — - single, = double, ~ triple — go between atoms, and each bond’s direction is set in the square brackets right after it. A digit 0–7 such as [2] is a predefined direction in 45° steps: [0] is east (right), and counterclockwise [2] is straight up, [4] west, [6] straight down. An arbitrary angle is written with a colon as an absolute value, e.g. [:30]. Parentheses (...) branch off from the main chain.
\usepackage{chemfig}
% ...
% methane: hydrogens west, up, down, east
\chemfig{H-C(-[2]H)(-[6]H)-H}
% benzene: alternating bonds, then the inscribed-circle form
\chemfig{*6(=-=-=-)}
\chemfig{**6(------)}In the methane example, H-C first puts a hydrogen west of the carbon; the branches (-[2]H) and (-[6]H) add hydrogens straight up and straight down; and the final -H extends one east (the default direction), giving the cross-shaped CH4. In the benzene, *6(...) means a six-membered ring and the =-=-=- inside alternates single and double bonds. * gives an ordinary ring, and doubling it to ** gives the aromatic form with an inscribed circle. chemfig also draws reaction schemes: wrap them in \schemestart ... \schemestop, lay out the molecules, and insert arrows with \arrow. Write \arrow{->[reagent]} to label an arrow with reagents or conditions, and \arrow{<=>} for an equilibrium arrow.
\schemestart
\chemfig{H-C(-[2]H)(-[6]H)-H}
\arrow{->[\small oxidation]}
\chemfig{O=C(-[2]H)-[6]H}
\schemestopThis is a left-to-right scheme running from the structural formula of methane, through a labelled arrow marking oxidation, to the structural formula of formaldehyde. Because chemfig sits on TikZ, it runs under pdfLaTeX, LuaLaTeX, or XeLaTeX and normally needs no extra driver setup (under DVI-based pLaTeX, specify dvipdfmx). TeX Live 2024 ships version 1.66, dated 28 December 2023, by Christian Tellechea.
Calling up whole rings as commands: XyMTeX
The other long-standing tool for structural formulas is XyMTeX (by Shinsaku Fujita), and its premise is the opposite of chemfig’s. Where chemfig draws bonds in one stroke, XyMTeX calls up whole rings and skeletons as commands and takes the substituents as arguments. Write \bzdrv{1==Cl;4==OH} and out comes a benzene ring bearing Cl at position 1 and OH at position 4 — you state what sits where by locant number, exactly as chemical nomenclature does. Its strength is setting complex fused polycyclics and substitution patterns reliably through fixed, structured commands.
\usepackage{xymtex}
% ...
% benzene with Cl at position 1 and OH at position 4
\bzdrv{1==Cl;4==OH}For work started fresh, most people choose chemfig, whose notation is more intuitive and whose upkeep is active. XyMTeX stays useful for maintaining manuscripts already written in it, and for anyone whose hand is at home with specifying positions by locant. It supports a standard LaTeX output mode along with PostScript and PDF modes.
tikz-feynman presupposes LuaLaTeX: the warnings pdfLaTeX gives
Compile it with LuaLaTeX. It will “run” under other engines, but automatic placement stops working, and the placement keys are not silently ignored — each one is reported as a warning. Trying it with pdflatex on TeX Live 2024 produced first "Package tikz-feynman Warning: LuaTeX is required if you wish to have vertices automatically placed.", then one line each for horizontal, node distance, level distance, and sibling distance saying "The key you tried to use ... requires LuaTeX. It will be ignored." The layout algorithm is written in Lua; switching to lualatex produced no warning at all.
One more thing: watch the compat number. The often-quoted \usepackage[compat=1.0.0]{tikz-feynman} produces a warning on TeX Live 2024: "Package tikz-feynman Warning: The preamble requested version 1.0.0, but the system version is 1.1.0. This may change some diagrams." What ships is 1.1.0, dated 5 February 2016, so compat=1.1.0 is the right thing to write. The key exists so that you find out when a package update would change your diagrams, which means the correct usage is to match the version actually installed (a mismatched major number is an error, not a warning).
% compile with lualatex
\usepackage[compat=1.1.0]{tikz-feynman}
% ...
% one-shot command: e+ e- -> mu+ mu- via a photon
\feynmandiagram [horizontal=a to b] {
i1 -- [fermion] a -- [fermion] i2,
a -- [photon] b,
f1 -- [fermion] b -- [fermion] f2,
};The figure is a textbook s-channel scattering: the pair on the left meets at vertex a, a wavy line — a photon — joins a to b, and on the right it splits into another pair. Line styles are set with [fermion] (a straight line with an arrow), [photon] (a wavy line), [gluon] (a coil), and so on, and vertices are created implicitly just by naming them. The horizontal=a to b is a layout hint meaning “place a and b horizontally” — precisely the key pdfLaTeX warned it would ignore. For precise placement, open a feynman environment inside a tikzpicture, place vertices with \vertex, and connect them with \diagram*.
feynmf and feynmp: a two-pass method born in 1989
This family typesets each figure outside LaTeX and imports the result — a two-pass method. feynmf uses METAFONT, feynmp uses MetaPost. The author is Thorsten Ohl, and the copyright in feynmf.sty reaches back to 1989 — earlier than LaTeX2e (1994). TeX Live 2024 ships v1.08, whose internal revision timestamps are still from 1996. Which is another way of saying it has needed no changes for close to thirty years.
The way you write it is declarative. Group figures by file name in an fmffile environment; inside an fmfgraph (or fmfgraph*), give the external legs to \fmfleft and \fmfright and the lines to \fmf{...}. You never write vertex coordinates — you state only which leg runs through which vertex to where, and placement is done for you. \fmf{fermion}{i1,v1,o1} means “draw a fermion line from i1 through v1 to o1”.
% feynmp-auto runs MetaPost for you: pdflatex -shell-escape document
\usepackage{feynmp-auto}
% ...
\begin{fmffile}{myfd}
\begin{fmfgraph*}(120,80)
\fmfleft{i1,i2}
\fmfright{o1,o2}
\fmf{fermion}{i1,v1,o1}
\fmf{photon}{v1,v2}
\fmf{fermion}{i2,v2,o2}
\end{fmfgraph*}
\end{fmffile}This is where the opening of the page comes back. On the feynmf route, the first LaTeX run writes out myfd.mf — a METAFONT source — and passing that through mf casts the figure as a font. The METAFONT report from the actual run on TeX Live 2024 read "Font metrics written on myfd.tfm" and "Output written on myfd.600gf (1 character, 4340 bytes)". One character for one diagram. The second LaTeX run is then simply setting character number one of that font into the text. The feynmp route, through MetaPost, produces an ordinary figure rather than a font, which is why a modern PDF workflow normally picks it.
In practice, loading feynmp-auto is easier — it automates the MetaPost run. But since it launches an external program, --shell-escape is required, and forgetting it is nasty: on TeX Live 2024 the run produced neither warning nor error and simply built a PDF with no figure in it. If a figure’s place comes out blank, suspect a missing -shell-escape first. With the flag, two passes are enough: mpost runs and the figure lands.
modiagram for MO diagrams: the MOdiagram environment is deprecated
Use the lower-case environment name, modiagram. Examples across the web — and an earlier version of this page — widely show \begin{MOdiagram}, but using that with modiagram 0.3a on TeX Live 2024 warns: "Package modiagram Warning: The environment MOdiagram is deprecated. Use modiagram instead." The figure still comes out, but there is no reason to keep using a name that is on its way out. Switch to lower case and the warning goes away.
A molecular-orbital (MO) diagram sits on the border between chemistry and physics: it shows how atomic orbitals (AOs) combine into bonding and anti-bonding molecular orbitals (MOs), stacked vertically by energy. The package built for exactly this is modiagram (by Clemens Niederberger; version 0.3a in TeX Live 2024), founded on TikZ. Load it with \usepackage{modiagram} and, inside the environment, write the left and right atomic orbitals with \atom and the molecular orbitals joining them with \molecule.
\usepackage{modiagram}
% ...
% lower-case environment name: MOdiagram is deprecated
\begin{modiagram}
\atom{left}{ 1s = {0; up} }
\atom{right}{ 1s = {0; up} }
\molecule{ 1sMO = {1; pair, } }
\end{modiagram}This is the simplest MO diagram there is, for the hydrogen molecule H2. \atom{left} and \atom{right} each place one spin-up electron in a 1s orbital (the 0 in {0; up} is the energy level), and \molecule merges the two into a bonding orbital holding an electron pair (pair). Give only the occupancy — up, down, pair — and the level heights as arguments, and a level diagram of horizontal lines and spin arrows assembles itself. Such diagrams can also be drawn in plain TikZ, but because modiagram specialises in MO conventions, it sets these standard figures more briefly and more correctly.
Choosing between them, and where compilation tends to snag
The choice follows straightforwardly from what you want to make. Chemical formulas and equations inside prose: mhchem. Structures and reaction schemes: chemfig (or XyMTeX where a command-based approach suits complex fused rings). Feynman diagrams: tikz-feynman (or feynmf / feynmp for older setups and legacy manuscripts). MO diagrams: modiagram. mhchem and chemfig are complements rather than rivals, and the common pattern is to use both in one document — mhchem for the equations in the text, chemfig for the displayed skeletons.
In experience, compilation snags come down to about three causes. The wrong engine — tikz-feynman’s layout needs LuaLaTeX. A missing --shell-escape — feynmp-auto drops the figure without a word. And the number of passes — feynmf / feynmp need two runs before the figure appears. On top of that, chemfig and modiagram are TikZ-based, so the arithmetic grows heavy as figures multiply. Caching figures with tikzexternalize, or compiling them alone with the standalone class, visibly cuts the waiting while you edit.