A pressure-temperature (P-T) phase diagram showing the boundaries between solid, liquid, and gas phases of a substance. The diagram includes the triple point where all three phases coexist and the critical point beyond which the liquid-gas distinction vanishes. This is one of the most fundamental diagrams in chemistry and physics, essential for understanding phase transitions and states of matter.

// anyplot.ai
// phase-diagram-pt: Thermodynamic Phase Diagram (Pressure-Temperature)
// Library: muix 7.29.1 | JavaScript 22.23.2
// Quality: 92/100 | Created: 2026-08-20
import { LineChart } from "@mui/x-charts/LineChart";
import { useXScale, useYScale } from "@mui/x-charts/hooks";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
const t = window.ANYPLOT_TOKENS;
const W = window.ANYPLOT_SIZE.width;
const H = window.ANYPLOT_SIZE.height;
const TITLE_H = 60;
// ChartsYAxis places the rotated axis label at `tickFontSize + tickSize + 10`
// px from the axis line (its only lever for that offset, independent of the
// actual rendered tick fontSize, which tickLabelStyle controls below) — sized
// to clear the widest pressure tick label ("100 kPa").
const Y_AXIS_LABEL_OFFSET_PX = 85;
// --- Data (representative water phase diagram, deterministic) --------------
// Boundary curves follow the Clausius-Clapeyron relation (sublimation,
// vaporization) and the Simon-Glatzel equation (melting, which captures
// water's anomalous negative solid-liquid slope), each anchored to the
// real IAPWS triple point and critical point of water.
const R = 8.314; // J / (mol K)
const TRIPLE_T = 273.16; // K
const TRIPLE_P = 611.657; // Pa
const CRITICAL_T = 647.1; // K
const CRITICAL_P = 22.064e6; // Pa
function makeSublimation() {
// Solid-gas boundary: L_sub ≈ 51 kJ/mol
const LR = 51000 / R;
const n = 30;
const T = [];
const P = [];
for (let i = 0; i < n; i += 1) {
const temp = 200 + (i * (TRIPLE_T - 200)) / (n - 1);
T.push(temp);
P.push(TRIPLE_P * Math.exp(-LR * (1 / temp - 1 / TRIPLE_T)));
}
return { T, P };
}
function makeVaporization() {
// Liquid-gas boundary, two Clausius-Clapeyron segments (triple->boiling,
// boiling->critical) so the curve passes through the normal boiling point.
const BOIL_T = 373.15;
const BOIL_P = 101325;
const LR1 = 43364 / R;
const LR2 = 39448 / R;
const n1 = 18;
const n2 = 24;
const T = [];
const P = [];
for (let i = 0; i < n1; i += 1) {
const temp = TRIPLE_T + (i * (BOIL_T - TRIPLE_T)) / (n1 - 1);
T.push(temp);
P.push(TRIPLE_P * Math.exp(-LR1 * (1 / temp - 1 / TRIPLE_T)));
}
for (let i = 1; i < n2; i += 1) {
const temp = BOIL_T + (i * (CRITICAL_T - BOIL_T)) / (n2 - 1);
T.push(temp);
P.push(BOIL_P * Math.exp(-LR2 * (1 / temp - 1 / BOIL_T)));
}
T[T.length - 1] = CRITICAL_T;
P[P.length - 1] = CRITICAL_P;
return { T, P };
}
function makeMelting() {
// Solid-liquid boundary via the Simon-Glatzel equation for ice Ih, whose
// negative "a" reproduces water's anomalous negative melting slope.
const a = -395.2e6;
const c = 9;
const n = 36;
const pMax = 2.4e8;
const logLo = Math.log10(TRIPLE_P);
const logHi = Math.log10(pMax);
const T = [];
const P = [];
for (let i = 0; i < n; i += 1) {
const p = Math.pow(10, logLo + (i * (logHi - logLo)) / (n - 1));
const temp = TRIPLE_T * Math.pow(1 + (p - TRIPLE_P) / a, 1 / c);
T.push(temp);
P.push(p);
}
return { T: T.reverse(), P: P.reverse() };
}
const melting = makeMelting();
const vaporization = makeVaporization();
const sublimation = makeSublimation();
const X_MIN = 190;
const X_MAX = 700;
const Y_MIN = 0.1;
const Y_MAX = 3e8;
const formatPressure = (v) => {
if (v >= 1e6) return `${v / 1e6} MPa`;
if (v >= 1e3) return `${v / 1e3} kPa`;
return `${v} Pa`;
};
// --- Phase-region labels, point markers and the supercritical guide --------
// (annotations are explicitly required by the spec: triple/critical points
// marked + annotated, phase regions clearly labeled)
function PhaseAnnotations() {
const xScale = useXScale("x-melt");
const yScale = useYScale("pressure");
const tripleX = xScale(TRIPLE_T);
const tripleY = yScale(TRIPLE_P);
const criticalX = xScale(CRITICAL_T);
const criticalY = yScale(CRITICAL_P);
const topY = yScale(Y_MAX);
const rightX = xScale(X_MAX);
const guide = {
stroke: t.inkSoft,
strokeDasharray: "8 6",
strokeWidth: 1.5,
opacity: 0.55,
};
const regionLabel = {
fill: t.ink,
fontSize: 22,
fontWeight: 600,
opacity: 0.5,
textAnchor: "middle",
};
return (
<g>
{/* Supercritical-fluid boundary, extending from the critical point */}
<line x1={criticalX} x2={criticalX} y1={criticalY} y2={topY} {...guide} />
<line x1={criticalX} x2={rightX} y1={criticalY} y2={criticalY} {...guide} />
{/* Phase region labels */}
<text x={xScale(235)} y={yScale(2e5)} {...regionLabel}>
Solid
</text>
<text x={xScale(460)} y={yScale(8e6)} {...regionLabel}>
Liquid
</text>
<text x={xScale(430)} y={yScale(30)} {...regionLabel}>
Gas
</text>
<text
x={xScale(678)}
y={yScale(8e7)}
fill={t.inkSoft}
fontSize={17}
fontWeight={500}
textAnchor="middle"
>
<tspan x={xScale(678)} dy="0">
Supercritical
</tspan>
<tspan x={xScale(678)} dy="1.2em">
fluid
</tspan>
</text>
{/* Triple point */}
<circle cx={tripleX} cy={tripleY} r={9} fill={t.ink} stroke={t.pageBg} strokeWidth={2} />
<text x={tripleX + 16} y={tripleY - 10} fill={t.ink} fontSize={16} fontWeight={600}>
Triple point
</text>
<text x={tripleX + 16} y={tripleY + 10} fill={t.inkSoft} fontSize={14}>
273.16 K, 611.7 Pa
</text>
{/* Critical point — both lines sit above the point, clear of the
incoming vaporization curve and the vertical supercritical guide */}
<circle cx={criticalX} cy={criticalY} r={10} fill={t.ink} stroke={t.pageBg} strokeWidth={2} />
<text
x={criticalX - 18}
y={criticalY - 34}
fill={t.ink}
fontSize={16}
fontWeight={600}
textAnchor="end"
>
Critical point
</text>
<text
x={criticalX - 18}
y={criticalY - 14}
fill={t.inkSoft}
fontSize={14}
textAnchor="end"
>
647.1 K, 22.06 MPa
</text>
</g>
);
}
// --- Chart (default-exported component — the harness mounts it) -------------
export default function Chart() {
return (
<Box
sx={{
width: W,
height: H,
display: "flex",
flexDirection: "column",
bgcolor: t.pageBg,
}}
>
<Typography
sx={{
height: TITLE_H,
display: "flex",
alignItems: "center",
justifyContent: "center",
color: t.ink,
fontSize: 34,
fontWeight: 500,
flexShrink: 0,
}}
>
phase-diagram-pt · javascript · muix · anyplot.ai
</Typography>
<LineChart
width={W}
height={H - TITLE_H}
skipAnimation
grid={{ horizontal: true }}
xAxis={[
{
id: "x-melt",
data: melting.T,
scaleType: "linear",
min: X_MIN,
max: X_MAX,
label: "Temperature (K)",
labelStyle: { fontSize: 18 },
tickLabelStyle: { fontSize: 15 },
tickNumber: 9,
},
{ id: "x-vap", data: vaporization.T, scaleType: "linear", min: X_MIN, max: X_MAX },
{ id: "x-sub", data: sublimation.T, scaleType: "linear", min: X_MIN, max: X_MAX },
]}
yAxis={[
{
id: "pressure",
scaleType: "log",
min: Y_MIN,
max: Y_MAX,
label: "Pressure (Pa, log scale)",
labelStyle: { fontSize: 18 },
tickLabelStyle: { fontSize: 15 },
tickFontSize: Y_AXIS_LABEL_OFFSET_PX,
tickInterval: [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8],
valueFormatter: formatPressure,
},
]}
series={[
{
id: "melting",
xAxisId: "x-melt",
yAxisId: "pressure",
data: melting.P,
label: "Solid–Liquid boundary (melting)",
color: t.palette[0],
showMark: false,
curve: "monotoneX",
},
{
id: "vaporization",
xAxisId: "x-vap",
yAxisId: "pressure",
data: vaporization.P,
label: "Liquid–Gas boundary (vaporization)",
color: t.palette[1],
showMark: false,
curve: "monotoneX",
},
{
id: "sublimation",
xAxisId: "x-sub",
yAxisId: "pressure",
data: sublimation.P,
label: "Solid–Gas boundary (sublimation)",
color: t.palette[2],
showMark: false,
curve: "monotoneX",
},
]}
slotProps={{
legend: {
position: { vertical: "bottom", horizontal: "middle" },
direction: "row",
labelStyle: { fontSize: 15 },
},
}}
sx={{
".MuiLineElement-series-melting": { strokeWidth: 3.5 },
".MuiLineElement-series-vaporization": { strokeWidth: 3.5 },
".MuiLineElement-series-sublimation": { strokeWidth: 3.5 },
}}
margin={{ left: 165, right: 60, top: 30, bottom: 120 }}
>
<PhaseAnnotations />
</LineChart>
</Box>
);
}
Part of Thermodynamic Phase Diagram (Pressure-Temperature) on anyplot.ai.