Chapter 3: Fundamentals of Phase Equilibria and Phase Diagrams

Phase Equilibria and Phase Diagrams

📖 Reading Time: 20-25 minutes 📊 Difficulty: Intermediate 💻 Code Examples: 8 📝 Exercises: 0

This chapter covers the fundamentals of Fundamentals of Phase Equilibria and Phase Diagrams, which 1. what is a phase?. You will learn essential concepts and techniques.

Learning Objectives

By studying this chapter, you will acquire the following skills:

1. What is a Phase?

1.1 Definition of Phase

In materials science, a phase refers to a physically and chemically homogeneous region. Phases are distinguished from other phases by distinct interfaces.

Definition and Characteristics of Phase

A phase is a state of matter with the following characteristics:

1.2 Types of Phases

Various phases exist in materials:

Type of PhaseDescriptionExamples
Gas phaseGaseous state. Large intermolecular distances, free motionH‚O vapor, Ar atmosphere
Liquid phaseLiquid state. Molecules closely packed but with fluidityLiquid water, molten metal (Fe liquid)
Solid phaseSolid state. Atoms arranged regularly or irregularlyIce (H‚O solid), Fe crystal
Crystalline phaseSolid phase with periodically arranged atoms±-Fe (BCC), ³-Fe (FCC)
Amorphous phaseSolid phase without long-range orderGlass (SiO‚ amorphous), metallic glass

Example: Phases of Pure Iron (Fe)

Pure iron exhibits different phases with different crystal structures depending on temperature:

These are called allotropes , phases of the same element with different crystal structures.

1.3 Difference Between Phase and Microstructure

Note: Phase and Microstructure are Different Concepts

Example: Pearlite microstructure is a microstructure in which two phases , ±-Fe (ferrite) and FeƒC (cementite), are arranged in a lamellar pattern.

2. Equilibrium State and Equilibrium Conditions

2.1 Definition of Equilibrium State

As learned in the previous chapter, under constant temperature and pressure, a system reaches equilibrium when Gibbs energy (G) is minimized. When multiple phases coexist, the equilibrium conditions are expressed more specifically.

Equilibrium Conditions in Multiphase Systems

For phases ±, ², ³ to coexist in equilibrium, the following conditions must be satisfied:

1. Thermal equilibrium : Temperature is equal in all phases

$$ T^\alpha = T^\beta = T^\gamma $$

2. Mechanical equilibrium : Pressure is equal in all phases (when interfacial tension is negligible)

$$ P^\alpha = P^\beta = P^\gamma $$

3. Chemical potential equilibrium : Chemical potential of each component is equal in all phases

$$ \mu_i^\alpha = \mu_i^\beta = \mu_i^\gamma \quad \text{(for component $i$)} $$

2.2 Physical Meaning of Chemical Potential Equilibrium

The chemical potential equilibrium condition $\mu_i^\alpha = \mu_i^\beta$ means that “the driving force for component $i$ to transfer from ± phase to ² phase is zero.”

Understanding Through Water Evaporation Equilibrium

Consider water in a cup repeatedly evaporating and condensing, eventually reaching a state where liquid and gas phases coexist:

The gas pressure at this equilibrium state is the saturated vapor pressure.

2.3 Flow for Determining Equilibrium Conditions

```mermaid
flowchart TD
    A[Initial state: Arbitrary temperature and pressure] --> B{Are T and P equalin all phases?}
    B -->|No| C[Thermal and mechanical equilibrationMake T and P uniform]
    C --> B
    B -->|Yes| D{For each component i,is ¼_i equal in all phases?}
    D -->|No| E[Mass transferHigh ¼ phase ’ Low ¼ phase]
    E --> D
    D -->|Yes| F[Chemical equilibrium achieved]
    F --> G[System Gibbs energyreaches minimum value]
    G --> H[Equilibrium state]

    style A fill:#fce7f3
    style F fill:#d1fae5
    style H fill:#dbeafe
```

3. Gibbs Phase Rule

3.1 Derivation and Meaning of the Phase Rule

The Gibbs phase rule is an important relation that determines the degrees of freedom in a system at equilibrium.

Gibbs Phase Rule

$$ F = C - P + 2 $$

Meaning of degrees of freedom $F$ : The number of variables that can be varied independently while maintaining equilibrium. If $F = 0$, invariant system (temperature, pressure, and composition all fixed); if $F = 1$, univariant system (e.g., pressure is determined when temperature is set).

3.2 Application Examples of the Phase Rule

=İ Code Example 1: Verification of Phase Rule in Various Systems Copy

# Requirements:
# - Python 3.9+
# - pandas>=2.0.0, <2.2.0

"""
Example: 3.2 Application Examples of the Phase Rule

Purpose: Demonstrate data manipulation and preprocessing
Target: Beginner to Intermediate
Execution time: 5-10 seconds
Dependencies: None
"""

import pandas as pd

# Gibbs phase rule: F = C - P + 2

# Degrees of freedom calculation for various systems
systems = [
    {
        "System": "Pure water (single phase)",
        "Components C": 1,
        "Phases P": 1,
        "Degrees of freedom F": 1 - 1 + 2,
        "Example": "Liquid water only ’ T, P can be varied independently"
    },
    {
        "System": "Boiling water (two-phase)",
        "Components C": 1,
        "Phases P": 2,
        "Degrees of freedom F": 1 - 2 + 2,
        "Example": "Liquid + gas ’ P (vapor pressure) is determined when T is set"
    },
    {
        "System": "Water triple point",
        "Components C": 1,
        "Phases P": 3,
        "Degrees of freedom F": 1 - 3 + 2,
        "Example": "Solid + liquid + gas ’ T, P both fixed (0.01°C, 611 Pa)"
    },
    {
        "System": "Fe-C alloy (single phase)",
        "Components C": 2,
        "Phases P": 1,
        "Degrees of freedom F": 2 - 1 + 2,
        "Example": "³-Fe (austenite) only ’ T, P, composition x can be varied independently"
    },
    {
        "System": "Fe-C alloy (two-phase)",
        "Components C": 2,
        "Phases P": 2,
        "Degrees of freedom F": 2 - 2 + 2,
        "Example": "±-Fe + FeƒC ’ Composition of each phase is determined when T, P are set"
    },
    {
        "System": "Fe-C eutectic point",
        "Components C": 2,
        "Phases P": 3,
        "Degrees of freedom F": 2 - 3 + 2,
        "Example": "Liquid + ±-Fe + FeƒC ’ Others are determined when T or P is set"
    }
]

df = pd.DataFrame(systems)

print("=" * 80)
print("Application Examples of Gibbs Phase Rule: F = C - P + 2")
print("=" * 80)
print(df.to_string(index=False))
print("=" * 80)

# Interpretation of degrees of freedom
print("\nInterpretation of Degrees of Freedom")
print("F = 0: Invariant system")
print("       ’ All intensive variables are fixed (e.g., triple point)")
print("\nF = 1: Univariant system")
print("       ’ Other variables are determined when one variable is set (e.g., boiling curve)")
print("\nF = 2: Bivariant system")
print("       ’ Two variables can be varied independently (e.g., single-phase region)")
print("\nF = 3: Trivariant system")
print("       ’ Three variables can be varied independently (e.g., single phase in binary system)")

Note: Phase Rule Applies Only to Equilibrium States

The Gibbs phase rule is valid only when the system is in thermodynamic equilibrium. It cannot be applied in the following cases:

4. Phase Diagrams of Unary Systems

4.1 Pressure-Temperature (P-T) Phase Diagram

Phase diagrams of unary systems (pure substances) are represented on a plot with pressure (P) and temperature (T) as axes. This diagram shows the regions where each phase is stable and the phase boundaries.

=İ Code Example 2: Pressure-Temperature Phase Diagram of Water (H‚O) Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

import numpy as np
import matplotlib.pyplot as plt

# Phase diagram data for water (simplified model)
# The actual phase diagram is more complex, but simplified for educational purposes

# Temperature range [°C]
T_solid_liquid = np.array([-100, 0, 0.01])  # Melting curve
T_liquid_vapor = np.linspace(0.01, 374, 100)  # Vaporization curve
T_solid_vapor = np.linspace(-100, 0.01, 50)  # Sublimation curve

# Vapor pressure by Clausius-Clapeyron equation (simplified)
def vapor_pressure_liquid(T_celsius):
    """Vapor pressure at liquid-gas boundary (approximate equation)"""
    T = T_celsius + 273.15  # K
    # Simplified version of Antoine equation
    P = 0.611 * np.exp(17.27 * T_celsius / (T_celsius + 237.3))  # kPa
    return P

def vapor_pressure_solid(T_celsius):
    """Vapor pressure at solid-gas boundary (sublimation pressure)"""
    T = T_celsius + 273.15  # K
    # Sublimation pressure is lower than liquid phase (simplified)
    P = 0.611 * np.exp(21.87 * T_celsius / (T_celsius + 265.5))  # kPa
    return P

# Pressure calculation
P_solid_liquid = np.array([101.325, 101.325, 0.611])  # Melting curve (nearly vertical)
P_liquid_vapor = vapor_pressure_liquid(T_liquid_vapor)
P_solid_vapor = vapor_pressure_solid(T_solid_vapor)

# Visualization
fig, ax = plt.subplots(figsize=(12, 8))

# Phase boundaries
ax.plot(T_solid_liquid, P_solid_liquid, 'b-', linewidth=2.5, label='Solid-liquid boundary (melting curve)')
ax.plot(T_liquid_vapor, P_liquid_vapor, 'r-', linewidth=2.5, label='Liquid-gas boundary (vaporization curve)')
ax.plot(T_solid_vapor, P_solid_vapor, 'g-', linewidth=2.5, label='Solid-gas boundary (sublimation curve)')

# Triple point
T_triple = 0.01  # °C
P_triple = 0.611  # kPa
ax.plot(T_triple, P_triple, 'ko', markersize=12, label=f'Triple point ({T_triple}°C, {P_triple} kPa)', zorder=10)

# Critical point
T_critical = 374  # °C
P_critical = 22064  # kPa
ax.plot(T_critical, P_critical, 'rs', markersize=12, label=f'Critical point ({T_critical}°C, {P_critical/1000:.1f} MPa)', zorder=10)

# Phase region labels
ax.text(-50, 50000, 'Solid\n(Ice)', fontsize=14, ha='center', weight='bold',
        bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.7))
ax.text(100, 50000, 'Liquid\n(Water)', fontsize=14, ha='center', weight='bold',
        bbox=dict(boxstyle='round', facecolor='lightcyan', alpha=0.7))
ax.text(100, 0.05, 'Gas\n(Steam)', fontsize=14, ha='center', weight='bold',
        bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.7))

# Atmospheric pressure line
ax.axhline(101.325, color='gray', linestyle='--', linewidth=1.5, alpha=0.7, label='Atmospheric pressure (101.325 kPa)')
ax.text(-80, 101.325 * 1.2, '1 atm', fontsize=10, color='gray')

ax.set_xlabel('Temperature [°C]', fontsize=13)
ax.set_ylabel('Pressure [kPa]', fontsize=13)
ax.set_title('Pressure-Temperature Phase Diagram of Water (H‚O)', fontsize=15, fontweight='bold')
ax.set_yscale('log')
ax.set_ylim([0.01, 100000])
ax.set_xlim([-100, 400])
ax.legend(fontsize=10, loc='upper left')
ax.grid(True, alpha=0.3, which='both')

plt.tight_layout()
plt.savefig('water_phase_diagram.png', dpi=150, bbox_inches='tight')
plt.show()

print("Important points in the water phase diagram:")
print(f"ûTriple point: {T_triple}°C, {P_triple} kPa (three-phase coexistence, F=0)")
print(f"ûCritical point: {T_critical}°C, {P_critical/1000:.1f} MPa (distinction between liquid and gas disappears)")
print(f"ûBoiling point at atmospheric pressure: 100°C (intersection of liquid-gas boundary and atmospheric pressure line)")
print(f"ûMelting point at atmospheric pressure: 0°C (intersection of solid-liquid boundary and atmospheric pressure line)")

4.2 How to Read Phase Diagrams

Basic Rules for Reading Phase Diagrams

Practical Example: Ice Polymorphs Under High Pressure

The water phase diagram actually contains more than 15 ice polymorphs (Ice I, II, III, …, XV). Phases other than ordinary ice (Ice Ih) are stable only under high pressure:

These are important research subjects in planetary science and materials physics.

5. Clapeyron Equation and Clausius-Clapeyron Equation

5.1 Clapeyron Equation

An important relation that expresses the slope of the phase boundary ($dP/dT$) in terms of the enthalpy and entropy of phase transition.

Clapeyron Equation

The slope of the transition boundary from phase ± to phase ² is:

$$ \frac{dP}{dT} = \frac{\Delta S_{\text{trans}}}{\Delta V_{\text{trans}}} = \frac{\Delta H_{\text{trans}}}{T \Delta V_{\text{trans}}} $$

=İ Code Example 3: Calculation of Melting Curve Slope Using Clapeyron Equation Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

"""
Example: $$ \frac{dP}{dT} = \frac{\Delta S_{\text{trans}}}{\Delta V_{

Purpose: Demonstrate data visualization techniques
Target: Intermediate
Execution time: 2-5 seconds
Dependencies: None
"""

import numpy as np
import matplotlib.pyplot as plt

# Data for water melting
T_m = 273.15  # Melting point [K]
Delta_H_fusion = 6010  # Heat of fusion [J/mol]
V_ice = 19.65e-6  # Molar volume of ice [m^3/mol]
V_water = 18.02e-6  # Molar volume of water [m^3/mol]
Delta_V = V_water - V_ice  # Molar volume change (negative value!)

# Slope of melting curve by Clapeyron equation
dP_dT = Delta_H_fusion / (T_m * Delta_V)  # [Pa/K]

print("=" * 60)
print("Calculation of Water Melting Curve Slope Using Clapeyron Equation")
print("=" * 60)
print(f"Melting point (0°C): {T_m} K")
print(f"Heat of fusion: {Delta_H_fusion} J/mol = {Delta_H_fusion/1000:.2f} kJ/mol")
print(f"Molar volume of ice: {V_ice * 1e6:.3f} cm³/mol")
print(f"Molar volume of water: {V_water * 1e6:.3f} cm³/mol")
print(f"Molar volume change ”V: {Delta_V * 1e6:.3f} cm³/mol (negative value!)")
print(f"\nMelting curve slope dP/dT: {dP_dT:.2e} Pa/K")
print(f"                          = {dP_dT / 1e6:.2f} MPa/K")
print(f"                          = {dP_dT / 101325:.2f} atm/K")
print("=" * 60)

print("\nInterpretation")
print("ûdP/dT < 0 (negative slope): Melting point decreases with increasing pressure")
print("ûThis abnormal behavior is due to ice having a larger volume than water")
print("ûThe slipperiness of ice skating is explained (partially) by this pressure melting")
print("ûMost substances have dP/dT > 0 (melting point increases with pressure)")

# Drawing the melting curve
P_0 = 101325  # Atmospheric pressure [Pa]
T_range = np.linspace(270, 276, 100)  # [K]
P_range = P_0 + dP_dT * (T_range - T_m)  # [Pa]

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# Left plot: Melting curve
ax1.plot((T_range - 273.15), P_range / 1e6, linewidth=2.5, color='#3b82f6')
ax1.axhline(P_0 / 1e6, color='gray', linestyle='--', linewidth=1, alpha=0.7, label='Atmospheric pressure')
ax1.axvline(0, color='gray', linestyle='--', linewidth=1, alpha=0.7, label='0°C')
ax1.plot(0, P_0 / 1e6, 'ro', markersize=10, label='Melting point (atmospheric pressure)', zorder=5)
ax1.set_xlabel('Temperature [°C]', fontsize=12)
ax1.set_ylabel('Pressure [MPa]', fontsize=12)
ax1.set_title('Solid-Liquid Boundary of Water (Melting Curve)', fontsize=13, fontweight='bold')
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)
ax1.set_xlim([-3, 3])

# Right plot: Melting point change due to pressure
pressures = np.linspace(0, 100, 100)  # [MPa]
T_melt = T_m + pressures * 1e6 / dP_dT  # [K]
ax2.plot(pressures, T_melt - 273.15, linewidth=2.5, color='#f093fb')
ax2.axhline(0, color='gray', linestyle='--', linewidth=1, alpha=0.7)
ax2.set_xlabel('Pressure [MPa]', fontsize=12)
ax2.set_ylabel('Melting Point [°C]', fontsize=12)
ax2.set_title('Change in Melting Point Due to Pressure', fontsize=13, fontweight='bold')
ax2.grid(True, alpha=0.3)

# Annotation: Pressure effect
ax2.text(50, -0.2, f'At 100 MPa, melting point\ndrops by approximately {(T_melt[-1] - T_m):.2f} K',
         ha='center', fontsize=10,
         bbox=dict(boxstyle='round', facecolor='#fce7f3', alpha=0.9))

plt.tight_layout()
plt.savefig('clapeyron_equation_water.png', dpi=150, bbox_inches='tight')
plt.show()

5.2 Clausius-Clapeyron Equation

At the liquid-gas or solid-gas boundary, the volume of the gas phase is overwhelmingly larger than the liquid or solid phase ($V_{\text{gas}} \gg V_{\text{liquid/solid}}$), so the Clapeyron equation can be simplified.

Clausius-Clapeyron Equation

For the liquid-gas boundary (vaporization curve):

$$ \frac{d \ln P}{dT} = \frac{\Delta H_{\text{vap}}}{RT^2} $$

Or, for pressure change from temperature change $T_1 \to T_2$:

$$ \ln \frac{P_2}{P_1} = -\frac{\Delta H_{\text{vap}}}{R} \left( \frac{1}{T_2} - \frac{1}{T_1} \right) $$

=İ Code Example 4: Vapor Pressure Curve Using Clausius-Clapeyron Equation Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

"""
Example: $$ \ln \frac{P_2}{P_1} = -\frac{\Delta H_{\text{vap}}}{R} \l

Purpose: Demonstrate data visualization techniques
Target: Intermediate
Execution time: 2-5 seconds
Dependencies: None
"""

import numpy as np
import matplotlib.pyplot as plt

# Gas constant
R = 8.314  # J/(mol·K)

# Heat of vaporization data for various substances
substances = {
    'H‚O': {'Delta_H_vap': 40660, 'T_boil': 373.15, 'P_boil': 101325, 'color': '#3b82f6'},
    'Ethanol': {'Delta_H_vap': 38560, 'T_boil': 351.45, 'P_boil': 101325, 'color': '#10b981'},
    'Acetone': {'Delta_H_vap': 29100, 'T_boil': 329.15, 'P_boil': 101325, 'color': '#f093fb'},
    'Benzene': {'Delta_H_vap': 30720, 'T_boil': 353.25, 'P_boil': 101325, 'color': '#f59e0b'}
}

# Temperature range [K]
T = np.linspace(250, 400, 200)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# Left plot: Temperature dependence of vapor pressure (logarithmic scale)
for name, data in substances.items():
    Delta_H = data['Delta_H_vap']
    T_boil = data['T_boil']
    P_boil = data['P_boil']
    color = data['color']

    # Clausius-Clapeyron equation
    ln_P_P0 = -(Delta_H / R) * (1/T - 1/T_boil)
    P = P_boil * np.exp(ln_P_P0)  # [Pa]

    ax1.plot(T - 273.15, P / 1000, linewidth=2.5, label=name, color=color)

    # Mark boiling point
    ax1.plot(T_boil - 273.15, P_boil / 1000, 'o', markersize=8, color=color)

ax1.axhline(101.325, color='gray', linestyle='--', linewidth=1.5, alpha=0.7, label='Atmospheric pressure')
ax1.set_xlabel('Temperature [°C]', fontsize=12)
ax1.set_ylabel('Vapor Pressure [kPa]', fontsize=12)
ax1.set_title('Vapor Pressure Curves of Various Substances', fontsize=13, fontweight='bold')
ax1.set_yscale('log')
ax1.set_ylim([0.1, 1000])
ax1.legend(fontsize=10, loc='upper left')
ax1.grid(True, alpha=0.3, which='both')

# Right plot: ln(P) vs 1/T (verification of linear relationship)
for name, data in substances.items():
    Delta_H = data['Delta_H_vap']
    T_boil = data['T_boil']
    P_boil = data['P_boil']
    color = data['color']

    T_inv = 1 / T  # [1/K]
    ln_P_P0 = -(Delta_H / R) * (1/T - 1/T_boil)
    ln_P = np.log(P_boil) + ln_P_P0

    ax2.plot(T_inv * 1000, ln_P, linewidth=2.5, label=name, color=color)

    # Annotation of slope (first substance only)
    if name == 'H‚O':
        slope = -Delta_H / R
        ax2.text(3.2, 10, f'Slope = -”H_vap/R\n= {slope:.0f} K',
                fontsize=9,
                bbox=dict(boxstyle='round', facecolor='#fce7f3', alpha=0.8))

ax2.set_xlabel('1000/T [1000/K]', fontsize=12)
ax2.set_ylabel('ln(P) [ln(Pa)]', fontsize=12)
ax2.set_title('Clausius-Clapeyron Plot', fontsize=13, fontweight='bold')
ax2.legend(fontsize=10, loc='upper right')
ax2.grid(True, alpha=0.3)
ax2.invert_xaxis()  # Make temperature increase direction to the right

plt.tight_layout()
plt.savefig('clausius_clapeyron_equation.png', dpi=150, bbox_inches='tight')
plt.show()

print("=" * 70)
print("Application of Clausius-Clapeyron Equation")
print("=" * 70)
for name, data in substances.items():
    Delta_H = data['Delta_H_vap']
    T_boil = data['T_boil']
    print(f"\n{name}")
    print(f"  Boiling point (1 atm): {T_boil - 273.15:.2f} °C")
    print(f"  Heat of vaporization: {Delta_H/1000:.1f} kJ/mol")

    # Calculate vapor pressure at 80°C
    T_target = 273.15 + 80  # K
    ln_ratio = -(Delta_H / R) * (1/T_target - 1/T_boil)
    P_target = 101325 * np.exp(ln_ratio)
    print(f"  Vapor pressure at 80°C: {P_target/1000:.2f} kPa")

print("\n" + "=" * 70)
print("Practical example: Vacuum distillation")
print("Substances with low vapor pressure (high boiling point) can be distilled at low temperatures by reducing pressure.")
print("Example: When water is distilled at 50 mmHg (approximately 6.7 kPa), the boiling point drops to approximately 33°C.")

6. Classification of Phase Transitions

6.1 Ehrenfest Classification

Phase transitions are classified by the continuity of derivatives of Gibbs energy (Ehrenfest classification).

Type of Phase TransitionDefinitionCharacteristicsExamples
First-order phase transition$G$ is continuous, but
$\frac{\partial G}{\partial T}$ is discontinuousûLatent heat present
ûVolume change present
ûTwo-phase coexistenceMelting, boiling, sublimation,
allotropic transformation (Fe: ±’³)
Second-order phase transition$G$, $\frac{\partial G}{\partial T}$ are continuous, but
$\frac{\partial^2 G}{\partial T^2}$ is discontinuousûNo latent heat
ûNo volume change
ûDiscontinuity in heat capacityParamagnetic-ferromagnetic transition (Fe: 770°C),
superconducting transition

How to Distinguish First-Order and Second-Order Phase Transitions

=İ Code Example 5: Gibbs Energy for First-Order and Second-Order Phase Transitions Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

"""
Example: How to Distinguish First-Order and Second-Order Phase Transi

Purpose: Demonstrate data visualization techniques
Target: Advanced
Execution time: 2-5 seconds
Dependencies: None
"""

import numpy as np
import matplotlib.pyplot as plt

# Temperature range
T = np.linspace(200, 400, 500)  # [K]
T_transition = 300  # Transition temperature [K]

# Model for first-order phase transition (assuming melting)
Delta_H_fusion = 5000  # J/mol
Delta_S_fusion = Delta_H_fusion / T_transition  # J/(mol·K)

G_solid_1st = 1000 * (T - 200)  # Gibbs energy of solid phase (simplified)
G_liquid_1st = 1000 * (T - 200) - Delta_S_fusion * (T - T_transition)  # Liquid phase

# Selection of stable phase (lower Gibbs energy)
G_stable_1st = np.minimum(G_solid_1st, G_liquid_1st)

# Model for second-order phase transition (assuming paramagnetic-ferromagnetic transition)
# Gibbs energy is continuous, but second derivative (heat capacity) is discontinuous
G_paramagnetic = 1000 * (T - 200) + 0.5 * (T - T_transition)**2
G_ferromagnetic = 1000 * (T - 200) + 2.0 * (T - T_transition)**2

# Selection of stable phase
G_stable_2nd = np.where(T < T_transition, G_ferromagnetic, G_paramagnetic)

# Visualization
fig, axes = plt.subplots(2, 3, figsize=(16, 10))

# ===== First-order phase transition =====
# Upper left: Gibbs energy
axes[0, 0].plot(T, G_solid_1st / 1000, 'b--', linewidth=2, label='Solid phase', alpha=0.7)
axes[0, 0].plot(T, G_liquid_1st / 1000, 'r--', linewidth=2, label='Liquid phase', alpha=0.7)
axes[0, 0].plot(T, G_stable_1st / 1000, 'k-', linewidth=3, label='Stable phase')
axes[0, 0].axvline(T_transition, color='gray', linestyle=':', alpha=0.5)
axes[0, 0].set_xlabel('Temperature [K]', fontsize=11)
axes[0, 0].set_ylabel('Gibbs Energy [kJ/mol]', fontsize=11)
axes[0, 0].set_title('First-Order Phase Transition: Gibbs Energy', fontsize=12, fontweight='bold')
axes[0, 0].legend(fontsize=9)
axes[0, 0].grid(True, alpha=0.3)

# Upper middle: Entropy (first derivative)
S_solid = -np.gradient(G_solid_1st, T)
S_liquid = -np.gradient(G_liquid_1st, T)
S_stable = -np.gradient(G_stable_1st, T)
axes[0, 1].plot(T, S_solid, 'b--', linewidth=2, alpha=0.7)
axes[0, 1].plot(T, S_liquid, 'r--', linewidth=2, alpha=0.7)
axes[0, 1].plot(T, S_stable, 'k-', linewidth=3)
axes[0, 1].axvline(T_transition, color='gray', linestyle=':', alpha=0.5)
axes[0, 1].set_xlabel('Temperature [K]', fontsize=11)
axes[0, 1].set_ylabel('Entropy [J/(mol·K)]', fontsize=11)
axes[0, 1].set_title('First-Order Phase Transition: Entropy (Discontinuous)', fontsize=12, fontweight='bold')
axes[0, 1].grid(True, alpha=0.3)
axes[0, 1].text(T_transition + 10, np.mean(S_stable), '”S = ”H/T\n(Latent heat present)',
               fontsize=9, bbox=dict(boxstyle='round', facecolor='yellow', alpha=0.7))

# Upper right: Heat capacity (second derivative)
C_p_solid = T * np.gradient(S_solid, T)
C_p_liquid = T * np.gradient(S_liquid, T)
C_p_stable = T * np.gradient(S_stable, T)
axes[0, 2].plot(T, C_p_stable, 'k-', linewidth=3)
axes[0, 2].axvline(T_transition, color='gray', linestyle=':', alpha=0.5)
axes[0, 2].set_xlabel('Temperature [K]', fontsize=11)
axes[0, 2].set_ylabel('Heat Capacity C_p [J/(mol·K)]', fontsize=11)
axes[0, 2].set_title('First-Order Phase Transition: Heat Capacity (Divergence)', fontsize=12, fontweight='bold')
axes[0, 2].grid(True, alpha=0.3)
axes[0, 2].set_ylim([-500, 500])

# ===== Second-order phase transition =====
# Lower left: Gibbs energy
axes[1, 0].plot(T, G_paramagnetic / 1000, 'b--', linewidth=2, label='Paramagnetic phase', alpha=0.7)
axes[1, 0].plot(T, G_ferromagnetic / 1000, 'r--', linewidth=2, label='Ferromagnetic phase', alpha=0.7)
axes[1, 0].plot(T, G_stable_2nd / 1000, 'k-', linewidth=3, label='Stable phase')
axes[1, 0].axvline(T_transition, color='gray', linestyle=':', alpha=0.5)
axes[1, 0].set_xlabel('Temperature [K]', fontsize=11)
axes[1, 0].set_ylabel('Gibbs Energy [kJ/mol]', fontsize=11)
axes[1, 0].set_title('Second-Order Phase Transition: Gibbs Energy (Continuous)', fontsize=12, fontweight='bold')
axes[1, 0].legend(fontsize=9)
axes[1, 0].grid(True, alpha=0.3)

# Lower middle: Entropy (first derivative, continuous)
S_para = -np.gradient(G_paramagnetic, T)
S_ferro = -np.gradient(G_ferromagnetic, T)
S_stable_2nd = -np.gradient(G_stable_2nd, T)
axes[1, 1].plot(T, S_stable_2nd, 'k-', linewidth=3)
axes[1, 1].axvline(T_transition, color='gray', linestyle=':', alpha=0.5)
axes[1, 1].set_xlabel('Temperature [K]', fontsize=11)
axes[1, 1].set_ylabel('Entropy [J/(mol·K)]', fontsize=11)
axes[1, 1].set_title('Second-Order Phase Transition: Entropy (Continuous)', fontsize=12, fontweight='bold')
axes[1, 1].grid(True, alpha=0.3)
axes[1, 1].text(T_transition + 10, np.mean(S_stable_2nd), '”S = 0\n(No latent heat)',
               fontsize=9, bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.7))

# Lower right: Heat capacity (second derivative, discontinuous)
C_p_stable_2nd = T * np.gradient(S_stable_2nd, T)
axes[1, 2].plot(T, C_p_stable_2nd, 'k-', linewidth=3)
axes[1, 2].axvline(T_transition, color='gray', linestyle=':', alpha=0.5)
axes[1, 2].set_xlabel('Temperature [K]', fontsize=11)
axes[1, 2].set_ylabel('Heat Capacity C_p [J/(mol·K)]', fontsize=11)
axes[1, 2].set_title('Second-Order Phase Transition: Heat Capacity (Discontinuous)', fontsize=12, fontweight='bold')
axes[1, 2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('phase_transition_classification.png', dpi=150, bbox_inches='tight')
plt.show()

print("Summary of phase transition classification:")
print("\nFirst-Order Phase Transition")
print("ûG: Continuous, S = -G/T: Discontinuous (latent heat present)")
print("ûExamples: Melting (solid ’ liquid), vaporization (liquid ’ gas)")
print("ûMeasurement: Peak appears in DSC (differential scanning calorimetry)")
print("\nSecond-Order Phase Transition")
print("ûG: Continuous, S: Continuous, C_p = T S/T: Discontinuous")
print("ûExamples: Ferromagnetic-paramagnetic transition (Curie temperature of Fe: 770°C)")
print("ûMeasurement: Step in heat capacity appears in DSC (not a peak)")

7. Lever Rule

7.1 Principle of the Lever Rule

In a two-phase region, when the average composition of the system is given, the quantity ratio (phase fraction) of each phase is determined by the lever rule. This is mathematically the same as the “principle of the lever.”

Lever Rule Formula

In a binary system, when the composition of ± phase is $x_\alpha$, the composition of ² phase is $x_\beta$, and the average composition of the system is $x_{\text{avg}}$ where $x_\alpha < x_{\text{avg}} < x_\beta$:

$$ \frac{n_\beta}{n_\alpha} = \frac{x_{\text{avg}} - x_\alpha}{x_\beta - x_{\text{avg}}} $$

Or, as mole fractions (mass fractions) of each phase:

$$ f_\alpha = \frac{x_\beta - x_{\text{avg}}}{x_\beta - x_\alpha}, \quad f_\beta = \frac{x_{\text{avg}} - x_\alpha}{x_\beta - x_\alpha} $$

Here, $f_\alpha + f_\beta = 1$.

Geometric Meaning of the Lever Rule

Imagine a lever. The fulcrum is at the average composition $x_{\text{avg}}$, the left end is at $x_\alpha$, and the right end is at $x_\beta$.

From the lever balance condition: $n_\alpha \times (x_{\text{avg}} - x_\alpha) = n_\beta \times (x_\beta - x_{\text{avg}})$

Rearranging this gives the lever rule formula above.

=İ Code Example 6: Calculation and Visualization of Lever Rule Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

import numpy as np
import matplotlib.pyplot as plt

# Two-phase region settings
x_alpha = 0.2  # Composition of ± phase
x_beta = 0.8   # Composition of ² phase

# Average composition range (within two-phase region)
x_avg_range = np.linspace(x_alpha, x_beta, 100)

# Phase fraction calculation by lever rule
def lever_rule(x_avg, x_alpha, x_beta):
    """Calculate fraction of each phase using lever rule"""
    f_alpha = (x_beta - x_avg) / (x_beta - x_alpha)
    f_beta = (x_avg - x_alpha) / (x_beta - x_alpha)
    return f_alpha, f_beta

f_alpha_range = []
f_beta_range = []
for x_avg in x_avg_range:
    f_a, f_b = lever_rule(x_avg, x_alpha, x_beta)
    f_alpha_range.append(f_a)
    f_beta_range.append(f_b)

f_alpha_range = np.array(f_alpha_range)
f_beta_range = np.array(f_beta_range)

# Visualization
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))

# Left plot: Change in phase fraction
ax1.plot(x_avg_range, f_alpha_range, linewidth=3, color='#3b82f6', label='± phase fraction $f_\\alpha$')
ax1.plot(x_avg_range, f_beta_range, linewidth=3, color='#f5576c', label='² phase fraction $f_\\beta$')
ax1.fill_between(x_avg_range, 0, f_alpha_range, alpha=0.3, color='#3b82f6')
ax1.fill_between(x_avg_range, f_alpha_range, 1, alpha=0.3, color='#f5576c')

# Boundary lines
ax1.axvline(x_alpha, color='gray', linestyle='--', linewidth=1.5, alpha=0.7)
ax1.axvline(x_beta, color='gray', linestyle='--', linewidth=1.5, alpha=0.7)
ax1.text(x_alpha, 1.05, f'$x_\\alpha={x_alpha}$', ha='center', fontsize=10)
ax1.text(x_beta, 1.05, f'$x_\\beta={x_beta}$', ha='center', fontsize=10)

# Mark specific example
x_example = 0.5
f_a_ex, f_b_ex = lever_rule(x_example, x_alpha, x_beta)
ax1.plot(x_example, f_a_ex, 'o', markersize=12, color='#10b981', zorder=5)
ax1.plot(x_example, f_b_ex, 'o', markersize=12, color='#10b981', zorder=5)
ax1.text(x_example + 0.05, f_a_ex, f'$x_{{avg}}={x_example}$\n$f_\\alpha={f_a_ex:.2f}$\n$f_\\beta={f_b_ex:.2f}$',
         fontsize=9, bbox=dict(boxstyle='round', facecolor='#d1fae5', alpha=0.9))

ax1.set_xlabel('Average Composition $x_{avg}$', fontsize=12)
ax1.set_ylabel('Phase Fraction [-]', fontsize=12)
ax1.set_title('Calculation of Phase Fraction Using Lever Rule', fontsize=13, fontweight='bold')
ax1.legend(fontsize=11, loc='center left')
ax1.grid(True, alpha=0.3)
ax1.set_xlim([x_alpha - 0.05, x_beta + 0.05])
ax1.set_ylim([0, 1.1])

# Right plot: Illustration of lever principle
ax2.axis('off')
ax2.set_xlim([0, 1])
ax2.set_ylim([0, 1])

# Drawing the lever
lever_y = 0.6
ax2.plot([x_alpha, x_beta], [lever_y, lever_y], 'k-', linewidth=4)
ax2.plot([x_alpha], [lever_y], 'o', markersize=15, color='#3b82f6', label='± phase')
ax2.plot([x_beta], [lever_y], 'o', markersize=15, color='#f5576c', label='² phase')
ax2.plot([x_example], [lever_y], '^', markersize=15, color='#10b981', label='Fulcrum (average composition)')

# Display distances
ax2.plot([x_alpha, x_example], [lever_y - 0.1, lever_y - 0.1], 'b-', linewidth=2)
ax2.text((x_alpha + x_example) / 2, lever_y - 0.15, f'${x_example - x_alpha:.1f}$',
         ha='center', fontsize=11, color='blue')
ax2.plot([x_example, x_beta], [lever_y - 0.1, lever_y - 0.1], 'r-', linewidth=2)
ax2.text((x_example + x_beta) / 2, lever_y - 0.15, f'${x_beta - x_example:.1f}$',
         ha='center', fontsize=11, color='red')

# Force arrows (corresponding to phase amounts)
arrow_y = 0.75
ax2.arrow(x_alpha, arrow_y, 0, -0.08, head_width=0.03, head_length=0.03,
          fc='#3b82f6', ec='#3b82f6', linewidth=2)
ax2.text(x_alpha, arrow_y + 0.05, f'$n_\\alpha$ or $f_\\alpha={f_a_ex:.2f}$',
         ha='center', fontsize=10, color='#3b82f6')

ax2.arrow(x_beta, arrow_y, 0, -0.08, head_width=0.03, head_length=0.03,
          fc='#f5576c', ec='#f5576c', linewidth=2)
ax2.text(x_beta, arrow_y + 0.05, f'$n_\\beta$ or $f_\\beta={f_b_ex:.2f}$',
         ha='center', fontsize=10, color='#f5576c')

# Explanation text
ax2.text(0.5, 0.35, 'Lever balance condition:\n$n_\\alpha \\times$ (right arm) $= n_\\beta \\times$ (left arm)',
         ha='center', fontsize=11,
         bbox=dict(boxstyle='round', facecolor='#fef3c7', alpha=0.9))
ax2.text(0.5, 0.2, f'$\\frac{{n_\\beta}}{{n_\\alpha}} = \\frac{{{x_example - x_alpha:.1f}}}{{{x_beta - x_example:.1f}}} = {f_b_ex / f_a_ex:.2f}$',
         ha='center', fontsize=12)

ax2.set_title('Geometric Meaning of Lever Rule', fontsize=13, fontweight='bold')
ax2.legend(fontsize=10, loc='upper left')

plt.tight_layout()
plt.savefig('lever_rule.png', dpi=150, bbox_inches='tight')
plt.show()

# Specific calculation examples
print("=" * 70)
print("Lever Rule Calculation Examples")
print("=" * 70)
print(f"± phase composition: x_± = {x_alpha}")
print(f"² phase composition: x_² = {x_beta}")
print(f"\nCase 1Average composition x_avg = {x_example}")
print(f"  ± phase fraction: f_± = (x_² - x_avg) / (x_² - x_±) = {f_a_ex:.3f} ({f_a_ex*100:.1f}%)")
print(f"  ² phase fraction: f_² = (x_avg - x_±) / (x_² - x_±) = {f_b_ex:.3f} ({f_b_ex*100:.1f}%)")
print(f"  Verification: f_± + f_² = {f_a_ex + f_b_ex:.3f} ")

x_example2 = 0.3
f_a_ex2, f_b_ex2 = lever_rule(x_example2, x_alpha, x_beta)
print(f"\nCase 2Average composition x_avg = {x_example2} (closer to ± phase)")
print(f"  ± phase fraction: f_± = {f_a_ex2:.3f} ({f_a_ex2*100:.1f}%)")
print(f"  ² phase fraction: f_² = {f_b_ex2:.3f} ({f_b_ex2*100:.1f}%)")
print(f"  ’ More ± phase (because average composition is closer to ± phase)")

x_example3 = 0.7
f_a_ex3, f_b_ex3 = lever_rule(x_example3, x_alpha, x_beta)
print(f"\nCase 3Average composition x_avg = {x_example3} (closer to ² phase)")
print(f"  ± phase fraction: f_± = {f_a_ex3:.3f} ({f_a_ex3*100:.1f}%)")
print(f"  ² phase fraction: f_² = {f_b_ex3:.3f} ({f_b_ex3*100:.1f}%)")
print(f"  ’ More ² phase (because average composition is closer to ² phase)")
print("=" * 70)

7.2 Practical Example of Lever Rule

Carbon Content and Microstructure in Steel

Consider the microstructure of Fe-C alloy (steel) at 727°C (eutectoid temperature):

Calculate the mass ratio of ferrite to cementite in eutectoid steel using the lever rule:

$f_{\text{Fe}_3\text{C}} = \frac{0.76 - 0.02}{6.7 - 0.02} = \frac{0.74}{6.68} \approx 0.11$ (11%)

$f_{\alpha\text{-Fe}} = 1 - 0.11 = 0.89$ (89%)

In other words, eutectoid steel consists of approximately 89% ferrite and 11% cementite.

8. Calculation of Phase Transformation Enthalpy

=İ Code Example 7: Determination and Visualization of Triple Point Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

"""
Example: 8. Calculation of Phase Transformation Enthalpy

Purpose: Demonstrate data visualization techniques
Target: Intermediate
Execution time: 10-30 seconds
Dependencies: None
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve

# Water phase transition data
data = {
    'Melting': {
        'Delta_H': 6010,  # J/mol
        'T_0': 273.15,    # K (0°C)
        'P_0': 101325,    # Pa
        'Delta_V': (18.02e-6 - 19.65e-6),  # m^3/mol (liquid - solid)
    },
    'Vaporization': {
        'Delta_H': 40660,  # J/mol
        'T_0': 373.15,     # K (100°C)
        'P_0': 101325,     # Pa
    },
    'Sublimation': {
        'Delta_H': 51000,  # J/mol (close to sum of melting + vaporization)
        'T_0': 273.15,     # K
        'P_0': 611,        # Pa (estimated)
    }
}

R = 8.314  # J/(mol·K)

# Equations for each boundary line
def melting_curve(T):
    """Solid-liquid boundary (Clapeyron)"""
    dP_dT = data['Melting']['Delta_H'] / (data['Melting']['T_0'] * data['Melting']['Delta_V'])
    P = data['Melting']['P_0'] + dP_dT * (T - data['Melting']['T_0'])
    return P

def vaporization_curve(T):
    """Liquid-gas boundary (Clausius-Clapeyron)"""
    Delta_H = data['Vaporization']['Delta_H']
    T_0 = data['Vaporization']['T_0']
    P_0 = data['Vaporization']['P_0']
    ln_ratio = -(Delta_H / R) * (1/T - 1/T_0)
    P = P_0 * np.exp(ln_ratio)
    return P

def sublimation_curve(T):
    """Solid-gas boundary (Clausius-Clapeyron)"""
    Delta_H = data['Sublimation']['Delta_H']
    T_0 = data['Sublimation']['T_0']
    P_0 = data['Sublimation']['P_0']
    ln_ratio = -(Delta_H / R) * (1/T - 1/T_0)
    P = P_0 * np.exp(ln_ratio)
    return P

# Determination of triple point (intersection of melting curve and sublimation curve)
def triple_point_equation(T):
    """Condition at triple point: melting curve pressure = sublimation curve pressure"""
    return melting_curve(T) - sublimation_curve(T)

T_triple = fsolve(triple_point_equation, 273.15)[0]
P_triple = sublimation_curve(T_triple)

print("=" * 60)
print("Triple Point Calculation Results")
print("=" * 60)
print(f"Temperature: {T_triple:.2f} K = {T_triple - 273.15:.2f} °C")
print(f"Pressure: {P_triple:.2f} Pa = {P_triple / 1000:.3f} kPa")
print("\nExperimental value (literature value):")
print("Temperature: 273.16 K = 0.01 °C")
print("Pressure: 611.657 Pa = 0.612 kPa")
print("\n’ Calculated value agrees well with experimental value")
print("=" * 60)

# Temperature range
T_range = np.linspace(250, 400, 300)
P_melt = melting_curve(T_range)
P_vap = vaporization_curve(T_range)
P_sub = sublimation_curve(T_range)

# Visualization
fig, ax = plt.subplots(figsize=(12, 8))

# Phase boundaries
T_melt_range = np.linspace(260, 280, 100)
T_vap_range = np.linspace(273, 374, 100)
T_sub_range = np.linspace(250, 273.16, 100)

ax.plot(T_melt_range - 273.15, melting_curve(T_melt_range) / 1000,
        'b-', linewidth=3, label='Solid-liquid boundary')
ax.plot(T_vap_range - 273.15, vaporization_curve(T_vap_range) / 1000,
        'r-', linewidth=3, label='Liquid-gas boundary')
ax.plot(T_sub_range - 273.15, sublimation_curve(T_sub_range) / 1000,
        'g-', linewidth=3, label='Solid-gas boundary')

# Triple point
ax.plot(T_triple - 273.15, P_triple / 1000, 'ko', markersize=14, zorder=10,
        label=f'Triple point\n({T_triple - 273.15:.2f}°C, {P_triple / 1000:.3f} kPa)')

# Phase rule display
ax.text(-15, 50, 'F = 2\n(Single-phase region)', fontsize=11, ha='center',
        bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.8))
ax.text(50, 50, 'F = 1\n(Two-phase coexistence line)', fontsize=11, ha='center',
        bbox=dict(boxstyle='round', facecolor='lightyellow', alpha=0.8))
ax.text(T_triple - 273.15 - 5, P_triple / 1000 + 0.3, 'F = 0\n(Three-phase coexistence point)',
        fontsize=10, ha='right',
        bbox=dict(boxstyle='round', facecolor='lightcoral', alpha=0.8))

ax.set_xlabel('Temperature [°C]', fontsize=13)
ax.set_ylabel('Pressure [kPa]', fontsize=13)
ax.set_title('Water Phase Diagram and Triple Point (Calculation Results)', fontsize=15, fontweight='bold')
ax.set_yscale('log')
ax.set_ylim([0.1, 200])
ax.set_xlim([-25, 105])
ax.legend(fontsize=11, loc='upper left')
ax.grid(True, alpha=0.3, which='both')

plt.tight_layout()
plt.savefig('triple_point_calculation.png', dpi=150, bbox_inches='tight')
plt.show()

9. Calculation of Phase Transition Temperatures in Real Materials

=İ Code Example 8: Calculation of Allotropic Transformation Temperatures for Fe and Ti Copy

# Requirements:
# - Python 3.9+
# - matplotlib>=3.7.0
# - numpy>=1.24.0, <2.0.0

"""
Example: 9. Calculation of Phase Transition Temperatures in Real Mate

Purpose: Demonstrate data visualization techniques
Target: Beginner to Intermediate
Execution time: 2-5 seconds
Dependencies: None
"""

import numpy as np
import matplotlib.pyplot as plt

# Allotropic transformation data for pure metals
metals = {
    'Fe (±’³)': {
        'T_trans': 912 + 273.15,  # K
        'Delta_H': 900,           # J/mol
        'phase_low': '±-Fe (BCC)',
        'phase_high': '³-Fe (FCC)',
        'color': '#f5576c'
    },
    'Fe (³’´)': {
        'T_trans': 1394 + 273.15,  # K
        'Delta_H': 840,            # J/mol
        'phase_low': '³-Fe (FCC)',
        'phase_high': '´-Fe (BCC)',
        'color': '#f093fb'
    },
    'Ti (±’²)': {
        'T_trans': 882 + 273.15,   # K
        'Delta_H': 4000,           # J/mol
        'phase_low': '±-Ti (HCP)',
        'phase_high': '²-Ti (BCC)',
        'color': '#3b82f6'
    },
    'Co (µ’±)': {
        'T_trans': 422 + 273.15,   # K
        'Delta_H': 450,            # J/mol
        'phase_low': 'µ-Co (HCP)',
        'phase_high': '±-Co (FCC)',
        'color': '#10b981'
    }
}

R = 8.314  # J/(mol·K)

# Pressure dependence of phase transition temperature calculation (Clapeyron approximation)
# Simplification: ”V estimated (typical value of 0.1 cm³/mol = 1e-7 m³/mol)
Delta_V_typical = 1e-7  # m³/mol

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6))

# Left plot: Comparison of allotropic transformation temperatures
metal_names = []
T_trans_list = []
Delta_H_list = []
colors = []

for name, data in metals.items():
    metal_names.append(name)
    T_trans_list.append(data['T_trans'] - 273.15)  # °C
    Delta_H_list.append(data['Delta_H'] / 1000)    # kJ/mol
    colors.append(data['color'])

x_pos = np.arange(len(metal_names))
ax1.bar(x_pos, T_trans_list, color=colors, alpha=0.7, edgecolor='black', linewidth=1.5)
ax1.set_xticks(x_pos)
ax1.set_xticklabels(metal_names, rotation=15, ha='right', fontsize=10)
ax1.set_ylabel('Transformation Temperature [°C]', fontsize=12)
ax1.set_title('Allotropic Transformation Temperatures of Pure Metals', fontsize=14, fontweight='bold')
ax1.grid(True, alpha=0.3, axis='y')

# Display values on each bar
for i, (T, DH) in enumerate(zip(T_trans_list, Delta_H_list)):
    ax1.text(i, T + 30, f'{T:.0f}°C\n”H={DH:.1f} kJ/mol',
             ha='center', fontsize=9,
             bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))

# Right plot: Relationship between transformation enthalpy and temperature
ax2.scatter(T_trans_list, Delta_H_list, s=200, c=colors, alpha=0.7,
            edgecolor='black', linewidth=2)
for name, T, DH, color in zip(metal_names, T_trans_list, Delta_H_list, colors):
    ax2.annotate(name, (T, DH), xytext=(10, 10), textcoords='offset points',
                fontsize=9,
                bbox=dict(boxstyle='round', facecolor=color, alpha=0.3),
                arrowprops=dict(arrowstyle='->', color='gray'))

ax2.set_xlabel('Transformation Temperature [°C]', fontsize=12)
ax2.set_ylabel('Transformation Enthalpy ”H [kJ/mol]', fontsize=12)
ax2.set_title('Relationship Between Transformation Temperature and Enthalpy', fontsize=14, fontweight='bold')
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('metal_allotropic_transformation.png', dpi=150, bbox_inches='tight')
plt.show()

# Display detailed data
print("=" * 80)
print("Allotropic Transformation Data for Pure Metals")
print("=" * 80)
for name, data in metals.items():
    print(f"\n{name}")
    print(f"  Transformation temperature: {data['T_trans'] - 273.15:.0f}°C ({data['T_trans']:.2f} K)")
    print(f"  Transformation enthalpy: {data['Delta_H']/1000:.2f} kJ/mol")
    print(f"  Low-temperature phase: {data['phase_low']}")
    print(f"  High-temperature phase: {data['phase_high']}")

    # Calculation of transformation entropy
    Delta_S = data['Delta_H'] / data['T_trans']  # J/(mol·K)
    print(f"  Transformation entropy: ”S = ”H/T = {Delta_S:.2f} J/(mol·K)")

print("\n" + "=" * 80)
print("Significance of Allotropic Transformations")
print("=" * 80)
print("ûFe ±’³ transformation: Basis of heat treatment in steel through quenching and tempering")
print("ûTi ±’² transformation: Improved plastic workability at high temperature (² processing)")
print("ûCo µ’± transformation: Application as magnetic material")
print("ûTransformation temperature can be controlled by alloying element addition (basis of phase diagram engineering)")

# Simple estimation of pressure effect
print("\n" + "=" * 80)
print("Change in Transformation Temperature Due to Pressure (Estimation)")
print("=" * 80)
for name, data in metals.items():
    T_trans = data['T_trans']
    Delta_H = data['Delta_H']
    # Clapeyron: dT/dP = T ”V / ”H
    dT_dP = T_trans * Delta_V_typical / Delta_H  # K/Pa
    dT_dP_MPa = dT_dP * 1e6  # K/MPa

    print(f"{name}: dT/dP H {dT_dP_MPa:.3f} K/MPa")
    print(f"  ’ Change of approximately {dT_dP_MPa * 100:.1f} K at 100 MPa")

Note: Pressure Dependence of Actual Phase Transition Temperatures

The above calculation is simplified for educational purposes. In reality:

Precise calculations use CALPHAD databases or first-principles calculations.

Summary

Key Points Learned in This Chapter

In the next chapter, we will proceed to binary phase diagrams and learn about phase equilibria in more complex alloy systems. We will cover phase diagram interpretation including eutectic reactions, peritectic reactions, and solid solutions, which are directly relevant to practical materials design.

=İ Exercises

Exercise 1: Application of Gibbs Phase Rule

Problem : Calculate the degrees of freedom $F$ for the following systems.

Hint : Use $F = C - P + 2$. Under constant pressure (atmospheric), $F = C - P + 1$.

Exercise 2: Application of Clapeyron Equation

Problem : For the ±’³ transformation of pure iron, calculate the pressure dependence of transformation temperature $dT/dP$ using the following data.

Hint : Use $dP/dT = \Delta H / (T \Delta V)$ and take the reciprocal to obtain $dT/dP$.

Exercise 3: Lever Rule Calculation

Problem : Consider the eutectoid reaction in Fe-C alloy (carbon steel) at 727°C. Calculate the mass ratio of ±-Fe (ferrite) to FeƒC (cementite) under the following conditions.

Hint : Use the lever rule $f_{\text{Fe}3\text{C}} = (x{\text{avg}} - x_\alpha) / (x_{\text{Fe}3\text{C}} - x\alpha)$.

Exercise 4: Vapor Pressure Curve Calculation (Hard)

Problem : Calculate the vapor pressure of ethanol at 20°C and 60°C using the following data.

Hint : Use the Clausius-Clapeyron equation $\ln(P_2 / P_1) = -(\Delta H_{\text{vap}} / R)(1/T_2 - 1/T_1)$. $P_1 = 101325$ Pa (1 atm), $T_1 = 78.3 + 273.15$ K.

References

  1. D.R. Gaskell, D.E. Laughlin, “Introduction to the Thermodynamics of Materials”, 6th Edition, CRC Press, 2017
  2. D.A. Porter, K.E. Easterling, M.Y. Sherif, “Phase Transformations in Metals and Alloys”, 3rd Edition, CRC Press, 2009
  3. P. Atkins, J. de Paula, “Atkins’ Physical Chemistry”, 11th Edition, Oxford University Press, 2018
  4. H.L. Lukas, S.G. Fries, B. Sundman, “Computational Thermodynamics: The CALPHAD Method”, Cambridge University Press, 2007
  5. J.W. Christian, “The Theory of Transformations in Metals and Alloys”, 3rd Edition, Pergamon Press, 2002

� Previous Chapter: Gibbs Energy and Chemical Potential Next Chapter: Binary Phase Diagrams and Phase Equilibria ’