🌐 EN | 🇯🇵 JP | Last sync: 2025-11-16

Chapter 2: Heat Treatment Processes

Annealing, Quenching & Tempering, Age Hardening, TTT/CCT Diagrams

=Ö Reading Time: 40-50 min =Ê Difficulty: Intermediate =» Code Examples: 7

Heat treatment processes are core technologies for controlling mechanical properties (strength, hardness, toughness) of materials. By controlling phase transformation, diffusion, and precipitation through temperature history of heating, holding, and cooling, target properties are achieved. This chapter covers learning the principles of annealing, quenching and tempering, and age hardening through Python simulations, and mastering practical heat treatment design using TTT/CCT diagrams.

Learning Objectives

By completing this chapter, you will be able to:

2.1 Annealing Process

2.1.1 Types and Purposes of Annealing

Annealing involves heating material to high temperature, holding, and slow cooling to achieve the following effects:

Annealing Type Purpose Temperature Range Microstructural Change
Full Annealing Softening, improved workability Acƒ + 30-50°C Ferrite + Pearlite
Stress Relief Annealing Residual stress removal 500-650°C No microstructural change
Recrystallization Annealing Work hardening removal, grain refinement 500-700°C New grain formation
Spheroidizing Annealing Carbide spheroidization, improved machinability Near Ac�, long duration Spheroidal cementite

2.1.2 Diffusion-Controlled Process and Holding Time

In annealing, atomic diffusion is the key to microstructural homogenization. According to Fick's Second Law, diffusion distance is proportional to the square root of time:

$$ x = \sqrt{D t} $$

Arrhenius equation (temperature dependence):

$$ D = D_0 \exp\left(-\frac{Q}{RT}\right) $$

Code Example 2-1: Calculating Diffusion Distance and Holding Time

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

import numpy as np
import matplotlib.pyplot as plt

def arrhenius_diffusion_coefficient(T_celsius, Q, D0):
    """
    Diffusion coefficient calculation using Arrhenius equation

    Parameters
    ----------
    T_celsius : float
        Temperature (°C)
    Q : float
        Activation energy (J/mol)
    D0 : float
        Frequency factor (m²/s)

    Returns
    -------
    D : float
        Diffusion coefficient (m²/s)
    """
    R = 8.314  # J/mol·K
    T_kelvin = T_celsius + 273.15

    D = D0 * np.exp(-Q / (R * T_kelvin))

    return D


def diffusion_distance(D, time):
    """
    Diffusion distance calculation

    Parameters
    ----------
    D : float
        Diffusion coefficient (m²/s)
    time : float
        Time (seconds)

    Returns
    -------
    x : float
        Diffusion distance (m)
    """
    x = np.sqrt(D * time)
    return x


# Carbon diffusion in iron (typical values)
Q_C_in_Fe = 142000  # J/mol
D0_C_in_Fe = 2.0e-5  # m²/s

# Simulation over temperature range
temperatures = np.array([700, 800, 900, 1000])  # °C
time_hours = np.linspace(0, 10, 100)  # Time (hours)
time_seconds = time_hours * 3600

plt.figure(figsize=(12, 6))

for T in temperatures:
    D = arrhenius_diffusion_coefficient(T, Q_C_in_Fe, D0_C_in_Fe)
    distances = [diffusion_distance(D, t) * 1e6 for t in time_seconds]  # ¼m

    plt.plot(time_hours, distances, linewidth=2, label=f'{T}°C')

    # Estimate holding time (reaching diffusion distance of 100 ¼m)
    target_distance = 100e-6  # m
    required_time = (target_distance ** 2) / D / 3600  # hours
    print(f"Temperature: {T}°C")
    print(f"  Diffusion Coefficient: {D:.2e} m²/s")
    print(f"  Time to diffuse 100 ¼m: {required_time:.2f} hours\n")

plt.xlabel('Time (hours)')
plt.ylabel('Diffusion Distance (¼m)')
plt.title('Carbon Diffusion in Iron (Annealing Process)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('diffusion_annealing.png', dpi=150, bbox_inches='tight')
plt.show()

# Results:
# 700°C to diffuse 100 ¼m ’ approximately 10 hours needed
# 1000°C to diffuse 100 ¼m ’ approximately 0.5 hours (30 minutes)
# ’ Higher temperature enables homogenization in shorter time

2.1.3 Recrystallization and Grain Growth

During annealing after cold working, recrystallization (nucleation and growth of new grains) and grain growth (grain boundary migration) occur.

Beck-Spaepen grain growth law:

$$ d^n - d_0^n = K t $$

Code Example 2-2: Grain Growth Simulation

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

import numpy as np
import matplotlib.pyplot as plt

def grain_growth(d0, K, time, n=2):
    """
    Beck-Spaepen grain growth model

    Parameters
    ----------
    d0 : float
        Initial grain size (¼m)
    K : float
        Growth constant (¼m^n / s)
    time : ndarray
        Time (seconds)
    n : int
        Growth exponent (default 2)

    Returns
    -------
    d : ndarray
        Grain size history (¼m)
    """
    d = (d0 ** n + K * time) ** (1 / n)
    return d


# Parameter settings
d0 = 10  # ¼m (initial grain size)
K = 0.5  # ¼m²/s (growth constant at 800°C)
time_hours = np.linspace(0, 10, 100)
time_seconds = time_hours * 3600

# Grain growth calculation
grain_size = grain_growth(d0, K, time_seconds, n=2)

# Plot
plt.figure(figsize=(10, 6))
plt.plot(time_hours, grain_size, 'b-', linewidth=2)
plt.xlabel('Annealing Time (hours)')
plt.ylabel('Average Grain Size (¼m)')
plt.title('Grain Growth during Annealing (800°C)')
plt.grid(True, alpha=0.3)
plt.axhline(y=50, color='r', linestyle='--', label='Target: 50 ¼m')
plt.legend()
plt.savefig('grain_growth.png', dpi=150, bbox_inches='tight')
plt.show()

# Calculate time to reach target grain size (50 ¼m)
target_size = 50  # ¼m
required_time = ((target_size ** 2) - (d0 ** 2)) / K
required_hours = required_time / 3600

print(f"Grain Growth Analysis:")
print(f"  Initial Grain Size: {d0} ¼m")
print(f"  Target Grain Size: {target_size} ¼m")
print(f"  Required Annealing Time: {required_hours:.2f} hours")
print(f"  Final Grain Size after 10h: {grain_size[-1]:.1f} ¼m")

2.2 Quenching and Tempering

2.2.1 Quenching and Martensitic Transformation

Quenching involves rapid cooling from austenite (³ phase) to produce martensite (supersaturated solid solution). Martensite has high hardness but high brittleness, so it is adjusted through tempering.

Cooling Rate Quenching Medium Resulting Microstructure Hardness (HV)
>200 °C/s Water, brine Martensite 600-800
50-200 °C/s Oil Martensite + Bainite 500-700
10-50 °C/s Air cooling Bainite 400-600
<10 °C/s Furnace cooling Pearlite 200-400

Newton's law of cooling (simplified model):

$$ \frac{dT}{dt} = -h (T - T_{\text{medium}}) $$

Code Example 2-3: Quenching Cooling Curve Simulation

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

import numpy as np
import matplotlib.pyplot as plt

def quenching_cooling_curve(T0, T_medium, h, time):
    """
    Cooling curve using Newton's law of cooling

    Parameters
    ----------
    T0 : float
        Initial temperature (°C)
    T_medium : float
        Quenching medium temperature (°C)
    h : float
        Cooling coefficient (1/s)
    time : ndarray
        Time (seconds)

    Returns
    -------
    T : ndarray
        Temperature history (°C)
    """
    T = T_medium + (T0 - T_medium) * np.exp(-h * time)
    return T


# Cooling condition settings
T_austenitize = 850  # °C (austenitizing temperature)
time = np.linspace(0, 60, 500)  # seconds

quenching_conditions = [
    {'name': 'Water Quench', 'T_med': 25, 'h': 0.3, 'color': 'blue'},
    {'name': 'Oil Quench', 'T_med': 60, 'h': 0.1, 'color': 'orange'},
    {'name': 'Air Cool', 'T_med': 25, 'h': 0.02, 'color': 'green'},
    {'name': 'Furnace Cool', 'T_med': 25, 'h': 0.005, 'color': 'red'}
]

plt.figure(figsize=(12, 8))

# Martensite start temperature (Ms) and bainite range
Ms_temp = 350  # °C
Bs_temp = 550  # °C

plt.axhline(y=Ms_temp, color='purple', linestyle='--', linewidth=2,
            label=f'Ms (Martensite Start): {Ms_temp}°C')
plt.axhspan(Bs_temp, Ms_temp, alpha=0.2, color='cyan',
            label='Bainite Range')

for cond in quenching_conditions:
    T_curve = quenching_cooling_curve(
        T_austenitize, cond['T_med'], cond['h'], time
    )
    plt.plot(time, T_curve, linewidth=2.5,
             color=cond['color'], label=cond['name'])

    # Cooling rate calculation (average from 800°C to 500°C)
    idx_800 = np.argmin(np.abs(T_curve - 800))
    idx_500 = np.argmin(np.abs(T_curve - 500))
    cooling_rate = (T_curve[idx_800] - T_curve[idx_500]) / (time[idx_500] - time[idx_800])

    print(f"{cond['name']}:")
    print(f"  Cooling Rate (800’500°C): {cooling_rate:.1f} °C/s")
    print(f"  Time to Ms ({Ms_temp}°C): {time[np.argmin(np.abs(T_curve - Ms_temp))]:.1f} s\n")

plt.xlabel('Time (s)')
plt.ylabel('Temperature (°C)')
plt.title('Quenching Cooling Curves and Microstructure Formation')
plt.legend(loc='upper right')
plt.grid(True, alpha=0.3)
plt.xlim(0, 60)
plt.ylim(0, 900)
plt.savefig('quenching_curves.png', dpi=150, bbox_inches='tight')
plt.show()

2.2.2 Jominy Hardenability Test

The Jominy test is a standard test method for evaluating hardenability of steel. One end is water-cooled, and hardness distribution is measured due to the cooling rate gradient.

flowchart LR A[Austenitizing
850°C, 30 min] --> B[Hold specimen
Water cool one end only] B --> C[Cooling rate gradient
End: Fast
Interior: Slow] C --> D[Hardness measurement
Distance from end vs HRC] D --> E[Hardenability evaluation
Gradual hardness drop = High] style A fill:#f093fb,stroke:#f5576c,stroke-width:2px,color:#fff style E fill:#f093fb,stroke:#f5576c,stroke-width:2px,color:#fff

Code Example 2-4: Jominy Hardenability Curve Simulation

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

import numpy as np
import matplotlib.pyplot as plt

def jominy_hardness_profile(distance_mm, HRC_max, DI, steel_type='Low Alloy'):
    """
    Jominy hardenability curve model

    Parameters
    ----------
    distance_mm : ndarray
        Distance from quenched end (mm)
    HRC_max : float
        Maximum hardness (HRC)
    DI : float
        Ideal Diameter (hardenability index)
    steel_type : str
        Steel grade

    Returns
    -------
    hardness : ndarray
        Hardness distribution (HRC)
    """
    # Grossmann hardenability model (simplified)
    # HRC = HRC_max * exp(-k * distance)
    k = 0.1 / DI  # Decay constant

    hardness = HRC_max * np.exp(-k * distance_mm)

    # Minimum hardness (ferrite + pearlite microstructure)
    HRC_min = 20
    hardness = np.maximum(hardness, HRC_min)

    return hardness


# Comparison of 3 steel types
distance = np.linspace(0, 50, 100)  # mm

steels = [
    {'name': 'S45C (Plain Carbon)', 'HRC_max': 62, 'DI': 10},
    {'name': 'SCM440 (Cr-Mo)', 'HRC_max': 60, 'DI': 30},
    {'name': 'SNC815 (Ni-Cr)', 'HRC_max': 58, 'DI': 50}
]

plt.figure(figsize=(12, 7))

for steel in steels:
    hardness = jominy_hardness_profile(distance, steel['HRC_max'], steel['DI'])
    plt.plot(distance, hardness, linewidth=2.5, label=steel['name'])

    # Hardenability evaluation (distance where hardness drops to HRC 50)
    idx_hrc50 = np.argmin(np.abs(hardness - 50))
    distance_hrc50 = distance[idx_hrc50]

    print(f"{steel['name']}:")
    print(f"  Maximum Hardness: {steel['HRC_max']} HRC")
    print(f"  Ideal Diameter (DI): {steel['DI']} mm")
    print(f"  Distance to HRC 50: {distance_hrc50:.1f} mm\n")

plt.axhline(y=50, color='k', linestyle='--', alpha=0.5, label='Target: HRC 50')
plt.xlabel('Distance from Quenched End (mm)')
plt.ylabel('Hardness (HRC)')
plt.title('Jominy Hardenability Test: Steel Comparison')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('jominy_hardenability.png', dpi=150, bbox_inches='tight')
plt.show()

# Result interpretation:
# - Plain Carbon (S45C): Low hardenability, only surface hardening
# - Cr-Mo (SCM440): Moderate hardenability
# - Ni-Cr (SNC815): High hardenability, hardening to deep sections

2.2.3 Tempering and Hardness Control

Tempering involves reheating quenched martensite at appropriate temperature to adjust the balance between hardness and toughness.

Hollomon-Jaffe equation (tempering parameter):

$$ P = T (C + \log_{10} t) \times 10^{-3} $$

Code Example 2-5: Tempering Hardness Prediction

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

import numpy as np
import matplotlib.pyplot as plt

def hollomon_jaffe_parameter(temp_celsius, time_hours, C=20):
    """
    Hollomon-Jaffe tempering parameter

    Parameters
    ----------
    temp_celsius : float
        Tempering temperature (°C)
    time_hours : float
        Tempering time (hours)
    C : float
        Constant (default 20)

    Returns
    -------
    P : float
        Tempering parameter
    """
    T_kelvin = temp_celsius + 273.15
    P = T_kelvin * (C + np.log10(time_hours)) * 1e-3

    return P


def tempered_hardness(P, HRC_initial=65):
    """
    Hardness prediction from tempering parameter

    Parameters
    ----------
    P : float
        Tempering parameter
    HRC_initial : float
        Initial hardness after quenching (HRC)

    Returns
    -------
    HRC : float
        Hardness after tempering (HRC)
    """
    # Empirical equation (varies by steel grade)
    HRC = HRC_initial - 0.15 * (P - 10) ** 1.5

    # Minimum hardness constraint
    HRC = np.maximum(HRC, 20)

    return HRC


# Temperature and time effect evaluation
temperatures = [200, 300, 400, 500, 600]  # °C
time_hours = np.logspace(-1, 2, 100)  # 0.1 to 100 hours

plt.figure(figsize=(12, 8))

for temp in temperatures:
    P_values = [hollomon_jaffe_parameter(temp, t) for t in time_hours]
    hardness = [tempered_hardness(P) for P in P_values]

    plt.plot(time_hours, hardness, linewidth=2.5, label=f'{temp}°C')

    # Time to reach target hardness (HRC 45)
    idx_target = np.argmin(np.abs(np.array(hardness) - 45))
    time_target = time_hours[idx_target]

    print(f"Tempering at {temp}°C:")
    print(f"  Time to reach HRC 45: {time_target:.2f} hours\n")

plt.axhline(y=45, color='k', linestyle='--', alpha=0.5, label='Target: HRC 45')
plt.xscale('log')
plt.xlabel('Tempering Time (hours)')
plt.ylabel('Hardness (HRC)')
plt.title('Tempering: Hardness vs Time and Temperature')
plt.legend()
plt.grid(True, alpha=0.3, which='both')
plt.savefig('tempering_hardness.png', dpi=150, bbox_inches='tight')
plt.show()

# Iso-hardness contour plot (2D map)
fig, ax = plt.subplots(figsize=(12, 8))

temp_range = np.linspace(150, 650, 50)
time_range = np.logspace(-1, 2, 50)
T_mesh, Time_mesh = np.meshgrid(temp_range, time_range)

Hardness_mesh = np.zeros_like(T_mesh)
for i in range(T_mesh.shape[0]):
    for j in range(T_mesh.shape[1]):
        P = hollomon_jaffe_parameter(T_mesh[i, j], Time_mesh[i, j])
        Hardness_mesh[i, j] = tempered_hardness(P)

contour = ax.contourf(T_mesh, Time_mesh, Hardness_mesh, levels=15, cmap='viridis')
contour_lines = ax.contour(T_mesh, Time_mesh, Hardness_mesh, levels=[40, 45, 50, 55, 60],
                             colors='white', linewidths=2)
ax.clabel(contour_lines, inline=True, fontsize=10, fmt='%d HRC')

ax.set_xlabel('Tempering Temperature (°C)')
ax.set_ylabel('Tempering Time (hours)')
ax.set_yscale('log')
ax.set_title('Tempering Map: Hardness Contours')
plt.colorbar(contour, label='Hardness (HRC)')
plt.savefig('tempering_map.png', dpi=150, bbox_inches='tight')
plt.show()

2.3 Age Hardening

2.3.1 Mechanism of Age Hardening

Age hardening (Precipitation Hardening) involves generating fine precipitates from supersaturated solid solution to inhibit dislocation movement and improve strength.

Age hardening process (Al alloy example):

  1. Solution Treatment: Dissolve alloying elements at high temperature (500-550°C)
  2. Quenching: Rapid cooling to room temperature, retaining supersaturated solid solution (SSSS)
  3. Aging Treatment: Precipitate formation at intermediate temperature (100-200°C)
    • GP zone (Guinier-Preston zone) formation
    • Intermediate phase (¸'', ¸') precipitation
    • Stable phase (¸, Mg‚Si) coarsening
flowchart LR A[Supersaturated
Solid Solution
SSSS] --> B[GP zone formation
Few nm] B --> C[Intermediate phase ¸''
Metastable] C --> D[¸' phase
Tens of nm] D --> E[Stable phase ¸
Coarsening] B -.-> F[Peak strength
Optimal precipitation] D -.-> G[Over-aging
Strength decrease] style A fill:#fce7f3,stroke:#f093fb,stroke-width:2px style F fill:#f093fb,stroke:#f5576c,stroke-width:2px,color:#fff style G fill:#fee2e2,stroke:#ef4444,stroke-width:2px

Orowan mechanism (precipitation strengthening):

$$ \Delta \sigma = \frac{M G b}{\lambda} $$

Code Example 2-6: Age Hardening Curve Simulation

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

import numpy as np
import matplotlib.pyplot as plt

def age_hardening_strength(time_hours, temp_celsius, k=0.5, n=0.3):
    """
    Age hardening strength change model (based on JMA equation)

    Parameters
    ----------
    time_hours : ndarray
        Aging time (hours)
    temp_celsius : float
        Aging temperature (°C)
    k : float
        Rate constant
    n : float
        Avrami exponent

    Returns
    -------
    strength : ndarray
        Tensile strength (MPa)
    """
    # Temperature dependence (Arrhenius type)
    k_eff = k * np.exp(-(5000 / (temp_celsius + 273.15)))

    # JMA equation (phase transformation fraction)
    f = 1 - np.exp(-(k_eff * time_hours) ** n)

    # Strength model
    sigma_0 = 100  # Solid solution strength (MPa)
    delta_sigma_max = 300  # Maximum precipitation strengthening (MPa)

    # After peak aging, decrease due to over-aging
    peak_fraction = 0.6
    strength = sigma_0 + delta_sigma_max * f * np.exp(-2 * (f - peak_fraction) ** 2)

    return strength


# Temperature dependence evaluation
temperatures = [150, 180, 200, 220]
time_hours = np.logspace(-1, 3, 200)  # 0.1 to 1000 hours

plt.figure(figsize=(12, 8))

for temp in temperatures:
    strength = age_hardening_strength(time_hours, temp)
    plt.plot(time_hours, strength, linewidth=2.5, label=f'{temp}°C')

    # Peak strength and time to reach
    peak_strength = np.max(strength)
    peak_time = time_hours[np.argmax(strength)]

    print(f"Age Hardening at {temp}°C:")
    print(f"  Peak Strength: {peak_strength:.1f} MPa")
    print(f"  Time to Peak: {peak_time:.2f} hours\n")

plt.xscale('log')
plt.xlabel('Aging Time (hours)')
plt.ylabel('Tensile Strength (MPa)')
plt.title('Age Hardening: Strength vs Time and Temperature')
plt.legend()
plt.grid(True, alpha=0.3, which='both')
plt.savefig('age_hardening_curve.png', dpi=150, bbox_inches='tight')
plt.show()

# Iso-strength contours (2D map)
fig, ax = plt.subplots(figsize=(12, 8))

temp_range = np.linspace(130, 250, 50)
time_range = np.logspace(-1, 3, 50)
T_mesh, Time_mesh = np.meshgrid(temp_range, time_range)

Strength_mesh = np.zeros_like(T_mesh)
for i in range(T_mesh.shape[0]):
    for j in range(T_mesh.shape[1]):
        strength_val = age_hardening_strength(np.array([Time_mesh[i, j]]), T_mesh[i, j])
        Strength_mesh[i, j] = strength_val[0]

contour = ax.contourf(T_mesh, Time_mesh, Strength_mesh, levels=15, cmap='plasma')
contour_lines = ax.contour(T_mesh, Time_mesh, Strength_mesh,
                             levels=[250, 300, 350, 380], colors='white', linewidths=2)
ax.clabel(contour_lines, inline=True, fontsize=10, fmt='%d MPa')

ax.set_xlabel('Aging Temperature (°C)')
ax.set_ylabel('Aging Time (hours)')
ax.set_yscale('log')
ax.set_title('Age Hardening Map: Strength Contours')
plt.colorbar(contour, label='Tensile Strength (MPa)')
plt.savefig('age_hardening_map.png', dpi=150, bbox_inches='tight')
plt.show()

2.4 Utilization of TTT and CCT Diagrams

2.4.1 TTT Diagram (Time-Temperature-Transformation)

The TTT diagram (isothermal transformation diagram) represents microstructural transformation during constant temperature holding. It is essential for steel heat treatment design.

Code Example 2-7: TTT/CCT Diagram Generation and Heat Treatment Simulation

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

import numpy as np
import matplotlib.pyplot as plt

def generate_TTT_diagram():
    """
    Generate simplified TTT diagram (eutectoid steel 0.8%C)
    """
    # Pearlite transformation start/finish curves (C curves)
    time = np.logspace(-1, 5, 200)  # seconds

    # Pearlite nose (fastest transformation at approximately 550°C)
    T_pearlite_start = 700 - 150 * np.exp(-((np.log10(time) - 1.5) / 1.5) ** 2)
    T_pearlite_finish = T_pearlite_start - 50

    # Bainite transformation (350-550°C)
    T_bainite_start = 500 - 150 * np.exp(-((np.log10(time) - 2.5) / 1.2) ** 2)
    T_bainite_finish = T_bainite_start - 50

    # Martensite start temperature (time-independent)
    Ms_temp = 250

    return time, T_pearlite_start, T_pearlite_finish, T_bainite_start, T_bainite_finish, Ms_temp


def simulate_cooling_path(cooling_rate, T_initial=850, time_max=1000):
    """
    Simulate cooling path

    Parameters
    ----------
    cooling_rate : float
        Cooling rate (°C/s)
    T_initial : float
        Initial temperature (°C)
    time_max : float
        Maximum time (seconds)

    Returns
    -------
    time, temperature : ndarray
        Cooling path
    """
    time = np.linspace(0, time_max, 500)
    temperature = T_initial - cooling_rate * time
    temperature = np.maximum(temperature, 25)  # Room temperature lower limit

    return time, temperature


# TTT diagram generation
time_ttt, T_p_start, T_p_finish, T_b_start, T_b_finish, Ms = generate_TTT_diagram()

# Plot
fig, ax = plt.subplots(figsize=(14, 10))

# TTT curves
ax.plot(time_ttt, T_p_start, 'r-', linewidth=2.5, label='Pearlite Start')
ax.plot(time_ttt, T_p_finish, 'r--', linewidth=2.5, label='Pearlite Finish')
ax.plot(time_ttt, T_b_start, 'b-', linewidth=2.5, label='Bainite Start')
ax.plot(time_ttt, T_b_finish, 'b--', linewidth=2.5, label='Bainite Finish')
ax.axhline(y=Ms, color='purple', linestyle='-', linewidth=2.5, label=f'Ms (Martensite): {Ms}°C')

# Region shading
ax.fill_between(time_ttt, T_p_start, T_p_finish, alpha=0.3, color='red', label='Pearlite Region')
ax.fill_between(time_ttt, T_b_start, T_b_finish, alpha=0.3, color='blue', label='Bainite Region')
ax.fill_between(time_ttt, 0, Ms, alpha=0.2, color='purple', label='Martensite Region')

# Overlay cooling paths
cooling_cases = [
    {'rate': 500, 'name': 'Water Quench (500°C/s)', 'color': 'green', 'linestyle': '-'},
    {'rate': 50, 'name': 'Oil Quench (50°C/s)', 'color': 'orange', 'linestyle': '-'},
    {'rate': 5, 'name': 'Air Cool (5°C/s)', 'color': 'brown', 'linestyle': '-'},
]

for case in cooling_cases:
    time_cool, temp_cool = simulate_cooling_path(case['rate'])
    ax.plot(time_cool, temp_cool, color=case['color'],
            linestyle=case['linestyle'], linewidth=3, label=case['name'])

ax.set_xscale('log')
ax.set_xlabel('Time (s)')
ax.set_ylabel('Temperature (°C)')
ax.set_title('TTT Diagram with Cooling Paths (Eutectoid Steel 0.8% C)')
ax.set_xlim(0.1, 1e4)
ax.set_ylim(0, 900)
ax.legend(loc='upper right', fontsize=9)
ax.grid(True, alpha=0.3, which='both')
plt.savefig('ttt_diagram_with_cooling.png', dpi=150, bbox_inches='tight')
plt.show()

# Microstructure prediction
print("Microstructure Prediction:")
for case in cooling_cases:
    time_cool, temp_cool = simulate_cooling_path(case['rate'])

    # Pearlite nose passage determination
    pearlite_time_min = time_ttt[np.argmin(T_p_start)]
    pearlite_temp_min = np.min(T_p_start)

    if case['rate'] > 100:
        microstructure = "100% Martensite (avoided pearlite nose)"
    elif case['rate'] > 20:
        microstructure = "Martensite + Bainite (partial transformation)"
    else:
        microstructure = "Pearlite + Ferrite (slow cooling)"

    print(f"{case['name']}: {microstructure}")

Exercises

Exercise 2-1: Annealing Holding Time Design (Easy)

For full annealing of carbon steel (0.5% C), you want to homogenize a 20 mm thick plate. The diffusion distance must reach at least 10 mm. Calculate the required holding time when annealing at 800°C. (Carbon diffusion coefficient: $D = 2.0 \times 10^{-5} \exp(-142000 / (8.314 \times T))$ m²/s, $T$ in K)

Solution Example
# Given conditions
target_distance = 10e-3  # m (10 mm)
T_celsius = 800
T_kelvin = T_celsius + 273.15

# Diffusion coefficient calculation
Q = 142000  # J/mol
D0 = 2.0e-5  # m²/s
R = 8.314    # J/mol·K

D = D0 * np.exp(-Q / (R * T_kelvin))

# Holding time calculation (x² = D * t)
t_required = (target_distance ** 2) / D
t_hours = t_required / 3600

print(f"Complete Annealing Time Calculation:")
print(f"  Temperature: {T_celsius} °C")
print(f"  Target Diffusion Distance: {target_distance*1000} mm")
print(f"  Diffusion Coefficient: {D:.2e} m²/s")
print(f"  Required Holding Time: {t_hours:.2f} hours ({t_required/60:.1f} min)")

# Result: Approximately 8 hours needed
# In practice, with safety margin, 10-12 hours holding is recommended

Exercise 2-2: Microstructure Prediction After Quenching (Easy)

After austenitizing eutectoid steel (0.8% C) at 850°C, predict the microstructure when quenched at the following cooling rates: (a) 200°C/s, (b) 30°C/s, (c) 3°C/s. Refer to the TTT diagram and answer the resulting microstructure and expected hardness range.

Solution Example

TTT Diagram Analysis:

  • (a) 200°C/s (water quench): Avoids pearlite nose (approximately 550°C, 1 second) ’ 100% Martensite, hardness HRC 64-66
  • (b) 30°C/s (oil quench): Passes through pearlite nose but short duration ’ Martensite + Upper Bainite, hardness HRC 55-60
  • (c) 3°C/s (air cooling): Long residence in pearlite transformation region ’ Fine Pearlite, hardness HRC 35-40

Experimental Verification: Ideally, measure with Jominy test and compare with predictions

Exercise 2-3: Tempering Condition Design (Medium)

You want to temper quenched tool steel (HRC 65) to target hardness HRC 55. Calculate the required time when tempering at 400°C and 500°C. (Use Hollomon-Jaffe parameter)

Solution Example
# Inverse calculation: Calculate P from target hardness, then calculate time
def inverse_tempered_hardness(HRC_target, HRC_initial=65):
    """Calculate Hollomon-Jaffe parameter from target hardness"""
    # HRC = HRC_initial - 0.15 * (P - 10)^1.5
    # ’ P = 10 + ((HRC_initial - HRC) / 0.15)^(2/3)
    P_target = 10 + ((HRC_initial - HRC_target) / 0.15) ** (2/3)
    return P_target

HRC_target = 55
P_target = inverse_tempered_hardness(HRC_target)

print(f"Target Hollomon-Jaffe Parameter: P = {P_target:.2f}\n")

# Calculate time for two temperatures
temperatures = [400, 500]  # °C

for temp in temperatures:
    T_kelvin = temp + 273.15
    C = 20

    # P = T * (C + log10(t)) * 1e-3
    # ’ log10(t) = (P / (T * 1e-3)) - C
    log10_t = (P_target / (T_kelvin * 1e-3)) - C
    t_hours = 10 ** log10_t

    print(f"Tempering at {temp}°C:")
    print(f"  Required Time: {t_hours:.2f} hours")
    print(f"  Practical Recommendation: {t_hours*1.2:.2f} hours (with safety margin)\n")

# Results:
# 400°C ’ Approximately 10 hours
# 500°C ’ Approximately 2 hours
# ’ Higher temperature reaches target hardness in shorter time

Exercise 2-4: Age Hardening Optimal Condition Determination (Medium)

For age hardening of Al-Cu alloy (Al-4%Cu), the target tensile strength is 400 MPa. If aging treatment can be performed at 180°C and 200°C, compare the optimal aging time and productivity (throughput) for each.

Solution Example
# Age hardening simulation (time to reach strength 400 MPa)
target_strength = 400  # MPa
temperatures = [180, 200]

time_hours_range = np.logspace(-1, 3, 500)

for temp in temperatures:
    strength_curve = age_hardening_strength(time_hours_range, temp)

    # Time to reach target strength
    idx_target = np.argmin(np.abs(strength_curve - target_strength))
    time_target = time_hours_range[idx_target]
    strength_achieved = strength_curve[idx_target]

    # Peak strength
    peak_strength = np.max(strength_curve)
    peak_time = time_hours_range[np.argmax(strength_curve)]

    print(f"Aging at {temp}°C:")
    print(f"  Time to reach {target_strength} MPa: {time_target:.2f} hours")
    print(f"  Achieved Strength: {strength_achieved:.1f} MPa")
    print(f"  Peak Strength: {peak_strength:.1f} MPa (at {peak_time:.2f} hours)")

    # Productivity evaluation (batch processing)
    batch_capacity = 100  # parts/batch
    throughput = batch_capacity / time_target  # parts/hour

    print(f"  Production Throughput: {throughput:.2f} parts/hour")
    print(f"  Daily Production (24h): {throughput*24:.0f} parts\n")

# Results:
# 180°C ’ Longer time but higher peak strength (stable)
# 200°C ’ Shorter time, higher productivity, but over-aging risk
# ’ Choose 200°C for productivity priority, 180°C for quality stability priority

Exercise 2-5: Hardenability Evaluation from Jominy Test Data (Medium)

The following hardness data were obtained from Jominy test: End surface (0 mm): HRC 62, 5 mm: HRC 58, 10 mm: HRC 52, 15 mm: HRC 45. From this data, predict the center hardness when quenching a 30 mm diameter round bar.

Solution Example
# Requirements:
# - Python 3.9+
# - numpy>=1.24.0, <2.0.0

"""
Example: The following hardness data were obtained from Jominy test: 

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

import numpy as np
from scipy.interpolate import interp1d

# Jominy test data
jominy_distance = np.array([0, 5, 10, 15])  # mm
jominy_hardness = np.array([62, 58, 52, 45])  # HRC

# Create interpolation function
interp_func = interp1d(jominy_distance, jominy_hardness,
                        kind='cubic', fill_value='extrapolate')

# Grossmann conversion table (simplified): Round bar diameter ’ Jominy equivalent distance
# Center of 30 mm diameter is equivalent to approximately 12-13 mm of Jominy test in terms of cooling rate
# (Actual conversion tables or H-band method should be used, but simplified calculation here)

diameter = 30  # mm
equivalent_jominy_distance = 0.4 * diameter  # Simplified conversion (center)

predicted_hardness = interp_func(equivalent_jominy_distance)

print(f"Jominy Hardenability Analysis:")
print(f"  Bar Diameter: {diameter} mm")
print(f"  Equivalent Jominy Distance (center): {equivalent_jominy_distance:.1f} mm")
print(f"  Predicted Center Hardness: {predicted_hardness:.1f} HRC")

# Surface hardness (Jominy 0 mm equivalent)
surface_hardness = interp_func(0)
print(f"  Predicted Surface Hardness: {surface_hardness:.1f} HRC")

# Case depth (depth with HRC e 50)
hardness_threshold = 50
try:
    depth_threshold = np.interp(hardness_threshold, jominy_hardness[::-1], jominy_distance[::-1])
    # Case depth in round bar (simplified conversion)
    effective_depth = depth_threshold / 0.4
    print(f"\nCase Depth (HRC e 50): {effective_depth:.1f} mm from surface")
except:
    print(f"\nCase Depth: Exceeds measurement range")

# Plot
plt.figure(figsize=(10, 6))
jominy_fine = np.linspace(0, 20, 100)
hardness_fine = interp_func(jominy_fine)
plt.plot(jominy_fine, hardness_fine, 'b-', linewidth=2, label='Interpolated Curve')
plt.scatter(jominy_distance, jominy_hardness, color='red', s=100,
            zorder=5, label='Measured Data')
plt.axvline(x=equivalent_jominy_distance, color='green', linestyle='--',
            linewidth=2, label=f'Equivalent Position (30mm bar center)')
plt.axhline(y=predicted_hardness, color='green', linestyle='--', alpha=0.5)
plt.xlabel('Distance from Quenched End (mm)')
plt.ylabel('Hardness (HRC)')
plt.title('Jominy Hardenability and Center Hardness Prediction')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('jominy_prediction.png', dpi=150, bbox_inches='tight')
plt.show()

Exercise 2-6: Heat Treatment Process Design Using TTT Diagram (Hard)

For eutectoid steel (0.8% C), you want to obtain a mixed microstructure of 50% martensite + 50% bainite. Design optimal cooling rate and isothermal holding conditions referring to TTT diagram. Target hardness is HRC 55-58.

Solution Example
# Strategy: Austempering
# 1. Austenitize at 850°C
# 2. Rapid quench to bainite region (e.g., 300°C) below Ms temperature (250°C)
# 3. Bainite transformation by isothermal holding (approximately 50%)
# 4. Cool to room temperature ’ Retained austenite transforms to martensite

T_austenitize = 850  # °C
T_austempering = 300  # °C (lower bainite region)
Ms = 250  # °C

# Cooling rate calculation (reach bainite region before entering below Ms)
# Must avoid pearlite nose (550°C, 1 second)
required_cooling_rate = (T_austenitize - T_austempering) / 5  # Within 5 seconds

print(f"Austempering Process Design:")
print(f"  Step 1: Austenitizing at {T_austenitize}°C")
print(f"  Step 2: Rapid quench to {T_austempering}°C")
print(f"    Required Cooling Rate: >{required_cooling_rate:.1f} °C/s")
print(f"    (Use oil or salt bath quench)")

# Bainite transformation time (read from TTT diagram)
# Transformation start at 300°C: approximately 10 seconds, 50% transformation: approximately 60 seconds
t_bainite_start = 10  # seconds
t_bainite_50pct = 60  # seconds

print(f"\n  Step 3: Isothermal hold at {T_austempering}°C")
print(f"    Bainite transformation starts: {t_bainite_start} s")
print(f"    Hold time for 50% bainite: {t_bainite_50pct} s")

# Retained austenite ’ Martensite transformation
print(f"\n  Step 4: Cool to room temperature")
print(f"    Remaining austenite (50%) transforms to martensite below {Ms}°C")

# Microstructure and hardness prediction
print(f"\nExpected Microstructure:")
print(f"  50% Lower Bainite (HRC 50-55)")
print(f"  50% Martensite (HRC 60-65)")
print(f"  Composite Hardness: HRC 55-58 ")

# Recommendation for experimental verification
print(f"\nExperimental Verification:")
print(f"  1. Conduct dilatometry to confirm transformation kinetics")
print(f"  2. Metallographic examination (SEM, optical microscopy)")
print(f"  3. Hardness testing (Rockwell C scale)")
print(f"  4. Impact toughness testing (Charpy) for quality assurance")

Exercise 2-7: Multi-Step Aging Treatment Optimization (Hard)

For Al-Mg-Si alloy, perform two-step aging treatment. Determine optimal conditions for Step 1 (low temperature, GP zone formation) and Step 2 (high temperature, intermediate phase precipitation) considering trade-off between tensile strength and cost (energy, time).

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

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

def two_step_aging_strength(t1_hours, T1_celsius, t2_hours, T2_celsius):
    """
    Two-step aging treatment strength prediction model

    Parameters
    ----------
    t1_hours, T1_celsius : float
        Step 1 aging (time, temperature)
    t2_hours, T2_celsius : float
        Step 2 aging (time, temperature)

    Returns
    -------
    strength : float
        Tensile strength (MPa)
    """
    # Step 1: GP zone formation (low temperature, long time)
    strength_step1 = 200 + 100 * (1 - np.exp(-0.5 * t1_hours)) * np.exp(-T1_celsius / 200)

    # Step 2: Intermediate phase precipitation (high temperature, short time)
    strength_step2 = 150 * (1 - np.exp(-0.2 * t2_hours)) * (1 - np.exp(-(T2_celsius - 150) / 50))

    # Composite strength
    total_strength = strength_step1 + strength_step2

    return total_strength


def calculate_cost(t1_hours, T1_celsius, t2_hours, T2_celsius):
    """
    Process cost calculation

    Returns
    -------
    cost : float
        Normalized cost (time + energy)
    """
    # Time cost (productivity)
    time_cost = t1_hours + t2_hours

    # Energy cost (temperature × time)
    energy_cost = (T1_celsius * t1_hours + T2_celsius * t2_hours) / 1000

    # Total cost (weighted)
    total_cost = time_cost + 0.5 * energy_cost

    return total_cost


def objective_function(params):
    """
    Multi-objective optimization objective function

    Maximize strength, minimize cost

    Returns
    -------
    -performance : float
        Negative performance index (minimization problem)
    """
    t1, T1, t2, T2 = params

    strength = two_step_aging_strength(t1, T1, t2, T2)
    cost = calculate_cost(t1, T1, t2, T2)

    # Performance index: strength / cost (higher is better)
    performance = strength / cost

    return -performance  # Convert to minimization problem


# Optimization execution
bounds = [
    (1, 24),    # t1: 1-24 hours
    (100, 150), # T1: 100-150°C
    (1, 12),    # t2: 1-12 hours
    (170, 220)  # T2: 170-220°C
]

result = differential_evolution(
    objective_function,
    bounds,
    maxiter=100,
    seed=42,
    disp=True
)

t1_opt, T1_opt, t2_opt, T2_opt = result.x
strength_opt = two_step_aging_strength(t1_opt, T1_opt, t2_opt, T2_opt)
cost_opt = calculate_cost(t1_opt, T1_opt, t2_opt, T2_opt)

print(f"Two-Step Aging Optimization Results:")
print(f"\nStep 1 (GP Zone Formation):")
print(f"  Temperature: {T1_opt:.1f} °C")
print(f"  Time: {t1_opt:.2f} hours")
print(f"\nStep 2 (Intermediate Phase Precipitation):")
print(f"  Temperature: {T2_opt:.1f} °C")
print(f"  Time: {t2_opt:.2f} hours")
print(f"\nPerformance:")
print(f"  Tensile Strength: {strength_opt:.1f} MPa")
print(f"  Total Process Cost: {cost_opt:.2f} (normalized)")
print(f"  Performance Index: {strength_opt/cost_opt:.2f} MPa/cost")

# Comparison: Single-step aging
T_single = 180
t_single = 10
strength_single = two_step_aging_strength(0, 100, t_single, T_single)
cost_single = calculate_cost(0, 100, t_single, T_single)

print(f"\nComparison with Single-Step Aging ({T_single}°C, {t_single}h):")
print(f"  Strength: {strength_single:.1f} MPa")
print(f"  Cost: {cost_single:.2f}")
print(f"  Performance Index: {strength_single/cost_single:.2f} MPa/cost")
print(f"\nImprovement:")
print(f"  Strength: +{strength_opt - strength_single:.1f} MPa ({(strength_opt/strength_single-1)*100:.1f}%)")
print(f"  Performance Index: +{(strength_opt/cost_opt) - (strength_single/cost_single):.2f} ({((strength_opt/cost_opt)/(strength_single/cost_single)-1)*100:.1f}%)")

Exercise 2-8: Statistical Quality Control of Heat Treatment Process (Hard)

In factory tempering process, there are variations of temperature ±5°C and time ±10%. Calculate the probability of achieving target hardness HRC 50±2 and evaluate process capability indices (Cp, Cpk). Propose improvement measures to keep defect rate below 1%.

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

"""
Example: In factory tempering process, there are variations of temper

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

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

# Process conditions (nominal values)
T_nominal = 450  # °C
t_nominal = 2.0  # hours
HRC_target = 50

# Process variation
T_std = 5 / 3  # °C (±5°C as 3Ã)
t_std = t_nominal * 0.1 / 3  # hours (±10% as 3Ã)

# Monte Carlo simulation
n_samples = 10000
np.random.seed(42)

T_samples = np.random.normal(T_nominal, T_std, n_samples)
t_samples = np.random.normal(t_nominal, t_std, n_samples)

# Hardness calculation (each sample)
hardness_samples = np.array([
    tempered_hardness(hollomon_jaffe_parameter(T, t))
    for T, t in zip(T_samples, t_samples)
])

# Statistical analysis
HRC_mean = np.mean(hardness_samples)
HRC_std = np.std(hardness_samples)

print(f"Process Capability Analysis:")
print(f"  Target Hardness: {HRC_target} ± 2 HRC")
print(f"  Actual Mean: {HRC_mean:.2f} HRC")
print(f"  Actual Std Dev: {HRC_std:.2f} HRC")

# Process capability indices
USL = HRC_target + 2  # Upper Specification Limit
LSL = HRC_target - 2  # Lower Specification Limit

Cp = (USL - LSL) / (6 * HRC_std)
Cpk = min((USL - HRC_mean) / (3 * HRC_std),
          (HRC_mean - LSL) / (3 * HRC_std))

print(f"\nProcess Capability Indices:")
print(f"  Cp = {Cp:.3f}")
print(f"  Cpk = {Cpk:.3f}")

if Cp >= 1.33:
    print(f"  ’ Cp assessment: CAPABLE (e1.33)")
else:
    print(f"  ’ Cp assessment: MARGINAL (<1.33)")

if Cpk >= 1.33:
    print(f"  ’ Cpk assessment: CAPABLE and CENTERED (e1.33)")
else:
    print(f"  ’ Cpk assessment: NEEDS IMPROVEMENT (<1.33)")

# Defect rate calculation
out_of_spec = np.sum((hardness_samples < LSL) | (hardness_samples > USL))
defect_rate = out_of_spec / n_samples * 100

print(f"\nDefect Rate:")
print(f"  Out of Specification: {out_of_spec} / {n_samples}")
print(f"  Defect Rate: {defect_rate:.2f}%")

if defect_rate < 1.0:
    print(f"  ’ Target (<1%) ACHIEVED ")
else:
    print(f"  ’ Target (<1%) NOT MET ")

# Histogram and process distribution
plt.figure(figsize=(12, 6))
plt.hist(hardness_samples, bins=50, density=True, alpha=0.7,
         color='blue', edgecolor='black', label='Actual Distribution')

# Normal distribution fit
x_fit = np.linspace(HRC_mean - 4*HRC_std, HRC_mean + 4*HRC_std, 200)
y_fit = norm.pdf(x_fit, HRC_mean, HRC_std)
plt.plot(x_fit, y_fit, 'r-', linewidth=2, label='Normal Fit')

# Specification limits
plt.axvline(x=LSL, color='green', linestyle='--', linewidth=2, label='LSL/USL')
plt.axvline(x=USL, color='green', linestyle='--', linewidth=2)
plt.axvline(x=HRC_target, color='black', linestyle='-', linewidth=2, label='Target')

# Shade out-of-spec regions
x_below = x_fit[x_fit < LSL]
y_below = norm.pdf(x_below, HRC_mean, HRC_std)
plt.fill_between(x_below, 0, y_below, color='red', alpha=0.3, label='Out of Spec')

x_above = x_fit[x_fit > USL]
y_above = norm.pdf(x_above, HRC_mean, HRC_std)
plt.fill_between(x_above, 0, y_above, color='red', alpha=0.3)

plt.xlabel('Hardness (HRC)')
plt.ylabel('Probability Density')
plt.title(f'Tempering Process Capability (Cp={Cp:.2f}, Cpk={Cpk:.2f})')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('process_capability.png', dpi=150, bbox_inches='tight')
plt.show()

# Improvement recommendations
print(f"\nImprovement Recommendations:")

if Cpk < 1.33:
    print(f"  Priority 1: Reduce process variation")
    print(f"    - Improve temperature control (±3°C target)")
    print(f"    - Calibrate furnace thermocouples")
    print(f"    - Implement SPC charts for real-time monitoring")

if abs(HRC_mean - HRC_target) > 0.5:
    print(f"  Priority 2: Center the process")
    print(f"    - Adjust nominal temperature to {T_nominal + (HRC_target - HRC_mean)*2:.1f}°C")

print(f"  Priority 3: Implement closed-loop control")
print(f"    - Measure hardness in-line (non-destructive testing)")
print(f"    - Adaptive control based on feedback")

# Simulation: Predicted improvement
T_std_improved = 3 / 3  # ±3°C
t_std_improved = t_nominal * 0.05 / 3  # ±5%

T_samples_improved = np.random.normal(T_nominal, T_std_improved, n_samples)
t_samples_improved = np.random.normal(t_nominal, t_std_improved, n_samples)

hardness_improved = np.array([
    tempered_hardness(hollomon_jaffe_parameter(T, t))
    for T, t in zip(T_samples_improved, t_samples_improved)
])

HRC_std_improved = np.std(hardness_improved)
Cp_improved = (USL - LSL) / (6 * HRC_std_improved)
defect_rate_improved = np.sum((hardness_improved < LSL) | (hardness_improved > USL)) / n_samples * 100

print(f"\nProjected Improvement (±3°C, ±5% time):")
print(f"  New Cp: {Cp_improved:.3f} (from {Cp:.3f})")
print(f"  New Defect Rate: {defect_rate_improved:.2f}% (from {defect_rate:.2f}%)")
print(f"  ’ Improvement: {defect_rate - defect_rate_improved:.2f}% reduction")

Exercise 2-9: Comprehensive Heat Treatment Simulation Project (Hard)

Design the entire manufacturing process for automotive gear (SCM440) (carburizing quenching ’ tempering ’ surface hardness HRC 58-62, core hardness HRC 35-40). Consider balance between process time, energy cost, and material properties, and determine optimal process using Python.

Solution Example
# Comprehensive process design framework
print("Comprehensive Heat Treatment Process Design for Automotive Gear (SCM440)")
print("="*70)

# Step 1: Carburizing
print("\nStep 1: Carburizing Process")
T_carburizing = 930  # °C
t_carburizing = 8    # hours (3mm carburized layer thickness)
case_depth = 3       # mm

print(f"  Temperature: {T_carburizing}°C")
print(f"  Time: {t_carburizing} hours")
print(f"  Target Case Depth: {case_depth} mm")
print(f"  Carbon Potential: 1.0-1.2%")

# Step 2: Diffusion Hold
print("\nStep 2: Diffusion Hold")
T_diffusion = 850  # °C
t_diffusion = 2    # hours
print(f"  Temperature: {T_diffusion}°C")
print(f"  Time: {t_diffusion} hours")
print(f"  Purpose: Uniform carbon distribution")

# Step 3: Quenching
print("\nStep 3: Quenching")
T_quench_start = 850
T_quench_medium = 60  # Oil temperature
cooling_rate = 50      # °C/s

print(f"  Quench Medium: Oil at {T_quench_medium}°C")
print(f"  Cooling Rate: ~{cooling_rate}°C/s")
print(f"  Expected Surface Microstructure: Martensite (HRC 60-64)")
print(f"  Expected Core Microstructure: Martensite + Bainite (HRC 45-50)")

# Step 4: Tempering
print("\nStep 4: Tempering")
T_tempering = 180  # °C (low-temperature tempering)
t_tempering = 2    # hours

# Hardness prediction (simplified)
P_surface = hollomon_jaffe_parameter(T_tempering, t_tempering)
HRC_surface_tempered = tempered_hardness(P_surface, HRC_initial=62)

print(f"  Temperature: {T_tempering}°C")
print(f"  Time: {t_tempering} hours")
print(f"  Expected Surface Hardness: HRC {HRC_surface_tempered:.0f}")
print(f"  Expected Core Hardness: HRC 35-40 (minimal change)")

# Process evaluation
print("\n" + "="*70)
print("Process Performance Evaluation:")

# Total process time
total_time = t_carburizing + t_diffusion + 0.5 + t_tempering  # Quenching 0.5h
print(f"  Total Process Time: {total_time:.1f} hours")

# Energy cost (simplified calculation)
# Furnace volume 1m³, heater efficiency 70%, electricity rate 0.15 USD/kWh
furnace_volume = 1.0  # m³
heat_capacity = 1200  # kJ/m³/°C
efficiency = 0.7

energy_carb = furnace_volume * heat_capacity * T_carburizing * t_carburizing / efficiency
energy_diff = furnace_volume * heat_capacity * T_diffusion * t_diffusion / efficiency
energy_temp = furnace_volume * heat_capacity * T_tempering * t_tempering / efficiency

total_energy = (energy_carb + energy_diff + energy_temp) / 3600  # kWh
energy_cost = total_energy * 0.15  # USD/batch

print(f"  Total Energy Consumption: {total_energy:.1f} kWh/batch")
print(f"  Energy Cost: ${energy_cost:.2f}/batch (100 gears)")
print(f"  Per-Gear Cost: ${energy_cost/100:.4f}")

# Material properties evaluation
print(f"\nTarget Material Properties:")
print(f"  Surface Hardness: HRC 58-62 (Target: {HRC_surface_tempered:.0f} )")
print(f"  Core Hardness: HRC 35-40 ")
print(f"  Case Depth: {case_depth} mm ")
print(f"  Core Toughness: Maintained by lower hardness")

# Optimization opportunities
print(f"\nOptimization Opportunities:")
print(f"  1. Use vacuum carburizing ’ Reduce time by 30%")
print(f"  2. Implement press quenching ’ Reduce distortion")
print(f"  3. Online hardness monitoring ’ Quality assurance")
print(f"  4. Energy recovery system ’ Reduce energy cost by 20%")

# Conclusion
print(f"\n" + "="*70)
print("Conclusion:")
print(f"  This process meets all specifications for automotive gears.")
print(f"  Total cycle time: {total_time:.1f} hours (competitive)")
print(f"  Energy efficiency: Moderate (improvement possible)")
print(f"  Quality assurance: Jominy testing + statistical process control recommended")

Learning Achievement Checklist

Basic Understanding Level

Practical Skills Level

Application Level

References

  1. Porter, D.A., Easterling, K.E., Sherif, M.Y. (2009). Phase Transformations in Metals and Alloys (3rd ed.). CRC Press, pp. 234-278, 345-389.
  2. Krauss, G. (2015). Steels: Processing, Structure, and Performance (2nd ed.). ASM International, pp. 145-189, 267-312.
  3. Honeycombe, R.W.K., Bhadeshia, H.K.D.H. (2017). Steels: Microstructure and Properties (4th ed.). Butterworth-Heinemann, pp. 89-124, 201-245.
  4. ASM International. (1991). ASM Handbook Volume 4: Heat Treating. ASM International, pp. 456-489, 567-602.
  5. Callister, W.D., Rethwisch, D.G. (2020). Materials Science and Engineering: An Introduction (10th ed.). Wiley, pp. 345-378, 412-456.
  6. Totten, G.E. (Ed.). (2006). Steel Heat Treatment: Metallurgy and Technologies (2nd ed.). CRC Press, pp. 123-167, 289-334.
  7. Polmear, I.J., StJohn, D., Nie, J.F., Qian, M. (2017). Light Alloys: Metallurgy of the Light Metals (5th ed.). Butterworth-Heinemann, pp. 178-223, 267-301.
  8. Brooks, C.R. (1996). Principles of the Heat Treatment of Plain Carbon and Low Alloy Steels. ASM International, pp. 56-89, 134-178.

Disclaimer