Once microstate probabilities are known, thermodynamic properties follow as ensemble averages. This section derives canonical expressions for internal energy, heat capacity, and pressure in terms of derivatives of lnQ. A recurring theme is that fluctuations are not a nuisance—they encode response functions such as CV.
Section 2.1 emphasized that macroscopic properties are expectation values of microscopic properties, with the expectation taken over the microstate probabilities. Section 2.2 derived the canonical probability distribution for a closed system’s microstates. Here, we connect these results by computing ensemble averages that determine macroscopic properties.
Learning objectives:
Compute internal energy both as an ensemble average, U=⟨E⟩, and as a derivative, U=−(∂lnQ/∂β)N,V.
Relate heat capacity to energy fluctuations via σE2=kBT2CV.
Compute pressure from the partition function using P=kBT(∂lnQ/∂V)N,T (when applicable).
Apply these formulas to simple discrete models (e.g., a two-state system).
Recall from Section 1.1 that thermodynamic equilibrium is a state of simultaneous mechanical, thermal, and chemical equilibrium. Below are working definitions of each type of equilibrium:
Thermal contact
A state in which two systems can exchange energy.
Chemical contact
A state in which two systems can exchange matter.
Mechanical equilibrium
A state in which the net force on each particle in the system is zero.
Thermal equilibrium
A state in which there is no net exchange of energy between systems in thermal contact.
Chemical equilibrium
A state in which there is no net exchange of matter between systems in chemical contact.
At fixed N, V, and T (equivalently fixed β), Q does not depend on the microstate index i. Therefore, it is constant with respect to the summation over i and can be pulled outside the sum.
import numpy as np
import matplotlib.pyplot as plt
from scipy.constants import k, eV
from labellines import labelLines
kB = k / eV # Boltzmann constant in eV/K
# Define the partition function for a two-state system
def partition_function_two_state(E1, E2, T):
beta = 1 / (kB * T)
return np.exp(-beta * E1) + np.exp(-beta * E2)
# Calculate the partition function for a two-state system
E1 = 0
E2 = 0.01 # Energy difference between the two states in eV
T_values = np.linspace(1, 1000, 1000)
Q_values = [partition_function_two_state(E1, E2, T) for T in T_values]
# Calculate the internal energy for a two-state system
beta_values = 1 / (kB * T_values)
ln_Q_values = np.log(Q_values)
U_values = -np.gradient(ln_Q_values, beta_values)
# Plot the internal energy as a function of temperature
fig, ax = plt.subplots(figsize=(4, 4))
ax.plot(T_values, U_values, 'k-')
ax.set_xlabel('Temperature (K)')
ax.set_ylabel('$U_{\\text{two-state}} - E_1$ (eV)')
ax.grid(True)
ax.annotate(
'$U_{\\text{two-state}} \\rightarrow E_1$', xy=(40, U_values[0] + 0.0001), xytext=(300, 0.001),
arrowprops=dict(arrowstyle='->', color='b'),
bbox=dict(boxstyle='round,pad=0.3', fc='w', ec='b'),
ha='center', va='center', color='b'
)
x_values_high_T = np.linspace(0, 1000, 1001)
y_values_high_T = ((E1 + E2) / 2) * np.ones_like(x_values_high_T)
line = ax.plot(x_values_high_T, y_values_high_T, 'm--', label='$U_{\\text{two-state}} \\rightarrow (E_1 + E_2) / 2$')
labelLines(line, zorder=2.5)
ax.set_xlim(0, 1000)
ax.set_ylim(0, 0.01)
plt.tight_layout()
plt.show()
plt.close(fig)
Internal energy of a two-state system as a function of temperature, for an energy gap of 0.01eV.
From Section 1.1, heat is energy transferred due to a temperature difference. The heat capacity at constant volume, CV, measures how much heat is required to change a system’s temperature at fixed N and V:
In statistics, the variance σX2 of a random variable X is σX2=⟨(X−⟨X⟩)2⟩. In statistical mechanics, σE2 quantifies fluctuations in the total energy:
In the canonical ensemble, a larger heat capacity corresponds to larger equilibrium energy fluctuations at fixed T. Smaller energy fluctuations correspond to smaller CV.
Complete Derivation of the CV and σE2 Relationship