Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
landau documentation
landau documentation
  • landau.py
  • Installation
  • API Reference
    • landau.phases
    • landau.interpolate
    • landau.plot
    • landau.calculate
    • landau.poly
    • landau.resample
  • Examples
    • Basics
    • Plot Gallery
    • Ideal Solution
    • Line Phases
    • Clausius-Clapeyron refiners on a regular solution
    • Toy Example
    • Mg/Ca Worked Example
Back to top
View this page

Plot Gallery¶

Every plotting helper in landau.plot at default settings, applied to one shared model system so the figures can be compared directly.

The system is three ideal solutions — fcc, hcp, liquid — ordered by the temperature at which each becomes stable (fcc lowest, liquid highest). The endpoint energies and entropies are loosely taken from the visual-review testplots (tests/integration/testplots.py). The numbers carry no physical meaning; they are chosen to produce a diagram in which all three phases appear.

Setup¶

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import landau.phases as ldp
import landau.calculate as ldc
import landau.plot as lpl

Each phase is an IdealSolution between an A endpoint (concentration 0) and a B endpoint (concentration 1). Higher entropy lowers the free energy faster with temperature, so the high-entropy liquid wins at high T while the low-entropy fcc wins at low T.

fcc = ldp.IdealSolution(
    "fcc",
    ldp.LinePhase("fccA", fixed_concentration=0, line_energy=-3.00, line_entropy=1.0 * ldp.kB),
    ldp.LinePhase("fccB", fixed_concentration=1, line_energy=-2.00, line_entropy=1.1 * ldp.kB),
)
hcp = ldp.IdealSolution(
    "hcp",
    ldp.LinePhase("hcpA", fixed_concentration=0, line_energy=-2.975, line_entropy=1.8 * ldp.kB),
    ldp.LinePhase("hcpB", fixed_concentration=1, line_energy=-1.95, line_entropy=1.1 * ldp.kB),
)
liquid = ldp.IdealSolution(
    "liquid",
    ldp.LinePhase("liquidA", fixed_concentration=0, line_energy=-2.75, line_entropy=5.0 * ldp.kB),
    ldp.LinePhase("liquidB", fixed_concentration=1, line_energy=-1.75, line_entropy=4.4 * ldp.kB),
)
phases = [fcc, hcp, liquid]

Overview¶

Every two-axis plotting helper at its default settings. The four panels share the same phases: a temperature cut at fixed chemical potential, a chemical potential cut at fixed temperature, and the two two-dimensional diagrams in concentration–temperature and chemical-potential–temperature space.

df_T = ldc.calc_phase_diagram(phases, np.linspace(100, 1000, 40), mu=0.0, keep_unstable=True)
df_mu = ldc.calc_phase_diagram(phases, Ts=800.0, mu=100, keep_unstable=True)
df_cT = ldc.calc_phase_diagram(phases, np.linspace(200, 1000, 50), mu=100)
df_muT = ldc.calc_phase_diagram(phases, np.linspace(200, 1000, 80), mu=np.linspace(0.5, 1.5, 80))

fig, axes = plt.subplots(2, 2, figsize=(12, 9))
lpl.plot_1d_T_phase_diagram(df_T, ax=axes[0, 0], show=False)
axes[0, 0].set_title("plot_1d_T_phase_diagram")
lpl.plot_1d_mu_phase_diagram(df_mu, ax=axes[0, 1], show=False)
axes[0, 1].set_title("plot_1d_mu_phase_diagram")
lpl.plot_phase_diagram(df_cT, ax=axes[1, 0], tielines=True)
axes[1, 0].set_title("plot_phase_diagram")
lpl.plot_mu_phase_diagram(df_muT, ax=axes[1, 1])
axes[1, 1].set_title("plot_mu_phase_diagram")
fig.tight_layout()
../_images/68f9602d9282bcb12b6de3f99bbdba34f08fc124ff27b84c808750044c3ead93.png

1D temperature scan¶

plot_1d_T_phase_diagram draws the semi-grand potential of every phase along a temperature cut at fixed chemical potential difference. The stable phase is solid, metastable branches are dashed; transitions are ticked on the top spine and each branch is labelled at its right end. Pass keep_unstable=True to calc_phase_diagram to retain the metastable branches.

df_T = ldc.calc_phase_diagram(phases, np.linspace(100, 1000, 40), mu=0.0, keep_unstable=True)
lpl.plot_1d_T_phase_diagram(df_T)
<Axes: xlabel='Temperature [K]', ylabel='Semi-grandcanonical potential [eV/atom]'>
../_images/ba4adf26877a39892be55be98cf62a1328bbd511e141a2f8e135bf8ddbd3f844.png

reference_phase subtracts that phase’s potential along the cut, which spreads out the small differences near the transitions.

lpl.plot_1d_T_phase_diagram(df_T, reference_phase="hcp")
<Axes: xlabel='Temperature [K]', ylabel='Semi-grandcanonical potential\nrelative to hcp [eV/atom]'>
../_images/b712ebb1306e8f118c64e828f3a3cf42cfc4aacfee7408d9c07157cdb589dd74.png

1D chemical-potential scan¶

plot_1d_mu_phase_diagram is the isothermal analogue: the semi-grand potential along a chemical-potential cut at fixed temperature. Here T = 800 K, where all three phases are stable over part of the range.

df_mu = ldc.calc_phase_diagram(phases, Ts=800.0, mu=100, keep_unstable=True)
lpl.plot_1d_mu_phase_diagram(df_mu)
<Axes: xlabel='Chemical Potential Difference [eV]', ylabel='Semi-grandcanonical Potential [eV/atom]'>
../_images/92f17f5480b0bd601973fd8edc438b91ca137e52fce527e2d7834341e0eb7e45.png
lpl.plot_1d_mu_phase_diagram(df_mu, reference_phase="hcp")
<Axes: xlabel='Chemical Potential Difference [eV]', ylabel='Semi-grandcanonical Potential\nrelative to hcp [eV/atom]'>
../_images/d147ed7c4527617c6f678698fda13893fdd1c7973341ecc4313222ee32217f3d.png

2D concentration–temperature diagram¶

plot_phase_diagram fills each stable phase region as a polygon in concentration–temperature space. tielines=True overlays the two-phase coexistence tielines. poly_method selects the polygon-construction strategy; the default depends on which optional extras are installed.

df_cT = ldc.calc_phase_diagram(phases, np.linspace(200, 1000, 50), mu=100)
fig, ax = plt.subplots(figsize=(6, 5))
lpl.plot_phase_diagram(df_cT, ax=ax, tielines=True)
../_images/e00ce43928c6fd11c359d3a7639fccc19b0ff6c7aa2cdd2872bb766320f5dcb2.png

Same diagram without tielines.

fig, ax = plt.subplots(figsize=(6, 5))
lpl.plot_phase_diagram(df_cT, ax=ax, tielines=False)
../_images/62299d830d61ec7fe5d86e6b34b96ccc664c727b1ed506679bd6ba369cb61ab4.png

2D chemical-potential–temperature diagram¶

plot_mu_phase_diagram plots the same equilibria in chemical-potential– temperature space, where the two-phase regions collapse to lines. Sample both axes so the refiner has a 2D grid to work with.

df_muT = ldc.calc_phase_diagram(phases, np.linspace(200, 1000, 80), mu=np.linspace(0.5, 1.5, 80))
fig, ax = plt.subplots(figsize=(6, 5))
lpl.plot_mu_phase_diagram(df_muT, ax=ax)
../_images/7f72b2f7c3b3f6ae6743fc0cbc8125994e59dc7812344c03476cf17637988e4f.png

Excess free energy¶

plot_excess_free_energy draws the excess free energy versus concentration, one facet per temperature, from a keep_unstable=True frame concatenated over several temperatures. With convex_hull=True the stable phases are solid, the metastable parts faded, and the common-tangent segments overlaid in black.

df_excess = pd.concat(
    [ldc.calc_phase_diagram(phases, Ts=T, mu=200, keep_unstable=True) for T in [400, 700, 1000]],
    ignore_index=True,
)
lpl.plot_excess_free_energy(df_excess, convex_hull=True)
<seaborn.axisgrid.FacetGrid at 0x7f266c323c90>
../_images/f068435e291c3b71a8eafdaeb0ab482f2b24ed470d840ed35f7c1df552158e19.png

Building polygons by hand¶

plot_phase_diagram is a thin wrapper over get_polygons + plot_polygons. Calling them directly gives control over the colour map (via get_phase_colors) and the axes, which is useful when overlaying a phase diagram on other artists.

polys = lpl.get_polygons(df_cT)
colors = lpl.get_phase_colors(df_cT["phase"].unique())

fig, ax = plt.subplots(figsize=(6, 5))
lpl.plot_polygons(polys, colors, ax=ax)
ax.autoscale()
ax.set_xlabel("$c$")
ax.set_ylabel("$T$ [K]")
ax.legend()
<matplotlib.legend.Legend at 0x7f266c403ed0>
../_images/39caaab7529f1b16811a392e2df2ae692a18501631b350d3ef91c19c863915cb.png
Next
Ideal Solution
Previous
Basics
Copyright © 2025, Marvin Poul
Made with Sphinx and @pradyunsg's Furo
On this page
  • Plot Gallery
    • Setup
    • Overview
    • 1D temperature scan
    • 1D chemical-potential scan
    • 2D concentration–temperature diagram
    • 2D chemical-potential–temperature diagram
    • Excess free energy
    • Building polygons by hand