Reproduced from Bartel et al. http://dx.doi.org/10.1007/s10853-022-06915-4. The convex hull of stability represents the lowest energy surface in composition space for a given chemical system. It is constructed by connecting the energies of the most thermodynamically stable compounds at each composition. For visual clarity, only ground-state phases at each composition are shown. Legend:
Materials on the hull are stable against decomposition into other phases. The energy difference between a material and the hull (hull distance) quantifies its thermodynamic stability - larger distances meaning less stable and harder to synthesize, making the convex hull a powerful tool for guiding experimental synthesis efforts.
\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, positioning, calc, intersections, shapes.misc}
\begin{document}
\begin{tikzpicture}[
>=Stealth,
point/.style={circle, fill, inner sep=3pt},
unstable/.style={rectangle, draw, fill=red, inner sep=3pt},
font=\Large,
line width=0.5pt,
reaction box/.style={rounded corners, draw=#1, fill=#1!5, text=#1, align=left, font=\small},
]
% Define the main coordinates
\coordinate (Origin) at (0,0);
\coordinate (TopLeft) at (0,8);
\coordinate (BottomRight) at (14,0);
\coordinate (TopRight) at (14,9);
\coordinate (AX) at (7,2);
\coordinate (A2X5) at (9.5,1.5);
% Axes
\draw[->] (Origin) -- ($(TopLeft)+(0,1)$);
\node[rotate=90, anchor=center] at ($(Origin)!0.5!(TopLeft)-(1,0)$) {$\Delta E_f$ (energy/atom)};
\draw (Origin) -- (BottomRight);
\draw[->] (BottomRight) -- (TopRight);
\node[below] at ($(Origin)!0.5!(BottomRight)$) {$x$ in $A_{1-x}X_x$};
% Convex hull
\node[blue!70!black, align=left, fill=white, inner sep=1pt] at (14,5) {convex hull\\of stability};
\draw[blue!70!black, line width=2.5pt, name path=hull]
(TopLeft) -- (AX) -- (A2X5) -- (14,7);
% Stable points
\node[point, blue!70!black] (A) at (TopLeft) {};
\node[point, blue!70!black] (AX) at (AX) {};
\node[point, blue!70!black] (A2X5) at (A2X5) {};
\node[point, blue!70!black] (X) at (14,7) {};
% Labels for stable points
\node[right=3pt of A] {A};
\node[below=3pt of AX] {AX};
\node[below=3pt of A2X5] {$A_2X_5$};
\node[left=3pt of X] {X};
% Unstable points
\node[unstable] (A2X) at ($(A)!0.5!(AX)+(0,2)$) {};
\node[unstable] (A2X7) at ($(A2X5)!0.15!(X)+(0,1.4)$) {};
% Labels for unstable points
\node[above=0pt of A2X] {$A_2X$};
\node[above left=-3pt of A2X7] {$A_2X_7$};
% Delta E arrows
\coordinate (A2X_hull) at ($(A)!0.5!(AX)$);
\draw[->, red, line width=1.5pt] (A2X_hull) -- (A2X) node[pos=0.65, left, red] {$\Delta E_d$};
\node[reaction box=red] at ($(A)!0.5!(AX)+(1.6,1.2)$) {$A + AX \to A_2X$};
% Hypothetical hull
\draw[gray, dashed, line width=1.5pt] (AX) -- (A2X7) -- (X);
\node[gray, above=3cm of $(A2X5)!0.1!(X)$, align=center] {hypothetical hull for\\evaluating $A_2X_5$};
% Delta E_d arrow for hypothetical hull
\coordinate (hull_midpoint) at ($(AX)!0.78!(A2X7)$);
\draw[->, green!50!black, line width=1.5pt] (hull_midpoint) -- (A2X5) node[pos=0.6, left, green!50!black] {$\Delta E_d$} node[reaction box=green!50!black,pos=0.6, right=0.1, line width=0.5pt] {$4/5 AX + 3/5 A_2X_7 \to A_2X_5$};
% Chemical potential range (orange line)
\coordinate (OrangeLow) at (0,5);
\draw[orange, dashed, line width=1.5pt] (OrangeLow) -- (AX)
node[pos=0.4, above, sloped, align=center] {$\mu_A$ range\\where $AX$ is stable};
% Orange double arrow
\draw[<->, orange, line width=1.5pt] ($(TopLeft)+(0.2,-0.2)$) -- ($(OrangeLow)+(0.2,0)$);
% Legend
\node[point, blue!70!black, label={right:stable}] at (0.5,1) {};
\node[unstable, label={right:unstable}] at (0.5,0.4) {};
\end{tikzpicture}
\end{document}
#import "@preview/cetz:0.3.2": canvas, draw, vector
#import draw: line, content, rect, circle, intersections
#set page(width: auto, height: auto, margin: 3pt)
#canvas({
// Diagram dimensions and styles
let width = 12
let height = 8
let point_radius = 0.15
let line_thickness = 1.5pt
let arrow_style = (mark: (end: "stealth"), stroke: black + line_thickness, fill: black)
let hull_style = (stroke: blue.darken(20%) + 2.5pt)
let hyp_hull_style = (stroke: (paint: gray, thickness: line_thickness, dash: "dashed"))
// Draw axes first to establish named positions
line((0, 0), (0, height), ..arrow_style, name: "y-axis-left")
line((0, 0), (width, 0), ..arrow_style, name: "x-axis")
line((width, 0), (width, height), ..arrow_style, name: "y-axis-right")
// Draw stable points
let stable_point(pos, label, anchor: "north", padding: none, ..rest) = {
circle(pos, radius: point_radius, fill: blue.darken(20%), ..rest)
content(pos, label, anchor: anchor, padding: padding)
}
stable_point((0, height - 1), "A", anchor: "west", padding: (left: 10pt), name: "a")
stable_point((width / 2, 2), "AX", anchor: "north", padding: (top: 10pt), name: "ax")
stable_point((width * 5 / 7, 1.5), $A_2X_5$, anchor: "north", padding: (top: 10pt), name: "a2x5")
stable_point((width, height - 1.5), "X", anchor: "east", padding: (right: 10pt), name: "x")
// Draw unstable points
let unstable_point(pos, label, ..rest) = {
let (x, y) = pos
rect((x, y - 0.15), (x + 0.3, y + 0.15), fill: red, stroke: .5pt, ..rest)
content(pos, label, anchor: "south", padding: (bottom: 8pt))
}
unstable_point((width / 3, height - 1.5), $A_2X$, name: "a2x")
unstable_point((width * 7 / 9, 3.7), $A_2X_7$, name: "a2x7")
// Draw convex hull
line("a", "ax", ..hull_style, name: "hull-a-ax")
line("ax", "a2x5", ..hull_style, name: "hull-ax-a2x5")
line("a2x5", "x", ..hull_style, name: "hull-a2x5-x")
content(
(rel: (-1.8, -.8), to: "ax"),
text(fill: blue.darken(20%), size: 12pt)[convex hull\ of stability],
frame: "rect",
stroke: none,
padding: (left: 5pt),
fill: white,
name: "hull-label",
)
line(
"hull-label.north",
"hull-a-ax.90%",
stroke: (paint: blue.darken(20%), thickness: .5pt),
padding: 1pt,
name: "hull-label-line",
)
// Draw hypothetical hull
line("ax", "a2x7", ..hyp_hull_style, name: "hyp-hull-ax-a2x7")
line("a2x7", "x", ..hyp_hull_style, name: "hyp-hull-a2x7-x")
content(
(rel: (0, 0.3), to: "hyp-hull-a2x7-x.mid"),
text(fill: gray, size: 13pt)[hypothetical hull for\ evaluating $A_2X_5$],
anchor: "east",
)
// Draw decomposition energy arrows
// First draw invisible lines to find intersections
line(
(rel: (0, 3), to: "a2x"),
(rel: (0, -3), to: "a2x"),
stroke: none,
name: "a2x-vertical",
)
intersections("a2x-isect", "a2x-vertical", "hull-a-ax", "hull-ax-a2x5")
// Draw arrow between intersection points
line(
"a2x-isect.0",
"a2x",
mark: (end: ">", fill: red),
stroke: red + line_thickness,
name: "arrow-a2x",
)
content(
(rel: (-0.5, 0), to: "arrow-a2x.60%"),
text(fill: red)[$Delta E_d$],
)
content(
(rel: (.2, 0), to: "arrow-a2x.30%"),
text(fill: red, size: 12pt)[A + AX → A₂X],
frame: "rect",
padding: (1pt, 3pt),
stroke: red + .3pt,
name: "box1",
anchor: "west",
fill: red.lighten(90%),
)
// Second arrow - find intersections first
line(
(rel: (0, 3), to: "a2x5"),
(rel: (0, -3), to: "a2x5"),
stroke: none,
name: "a2x5-vertical",
)
intersections("a2x5-isect", "a2x5-vertical", "hyp-hull-ax-a2x7", "hyp-hull-a2x7-x")
// Draw arrow between intersection points
line(
"a2x5-isect.0",
"a2x5",
mark: (end: ">", fill: rgb("#4d8000")),
stroke: rgb("#4d8000") + line_thickness,
name: "arrow-a2x5",
)
content(
"arrow-a2x5.mid",
text(fill: rgb("#4d8000"))[$Delta E_d$],
anchor: "east",
padding: (right: 3pt),
)
content(
(rel: (0.1, 0), to: "arrow-a2x5.mid"),
text(fill: rgb("#4d8000"), size: 10pt)[4/5 AX + 3/5 A₂X₇ → A₂X₅],
frame: "rect",
padding: (1pt, 3pt),
stroke: rgb("#4d8000") + .3pt,
name: "box2-label",
anchor: "west",
fill: rgb("#4d8000").lighten(90%),
)
// Draw chemical potential range
line(
(0, height - 4.5),
"ax",
stroke: (paint: orange, thickness: line_thickness, dash: "dashed"),
name: "mu-line",
)
content(
(rel: (2.4, 0), to: "mu-line.start"),
rotate(14deg)[#text(fill: orange, size: 13pt)[$μ_A$ range\ where AX is stable]],
)
// Draw orange double arrow
line(
"hull-a-ax.2%",
"mu-line.4%",
mark: (start: ">", end: ">", fill: orange),
stroke: orange + line_thickness,
name: "mu-arrow",
)
// Draw legend
circle((0.5, 1), radius: point_radius, fill: blue.darken(20%), name: "legend-stable")
content(
"legend-stable.east",
"stable",
anchor: "west",
padding: (left: 5pt),
)
rect(
(rel: (-0.15, -0.6), to: "legend-stable"),
(rel: (0.15, -0.3), to: "legend-stable"),
fill: red,
stroke: red,
name: "legend-unstable",
)
content(
"legend-unstable.east",
"unstable",
anchor: "west",
padding: (left: 5pt),
)
// Add axis labels
content(
(rel: (-0.5, 0), to: "y-axis-left.mid"),
[#rotate(-90deg)[$Delta E_f$ (energy/atom)]],
)
content((width / 2, -0.5), $x "in" A_(1-x)X_x$)
})