🎯 学習目標
- 固溶体と金属間化合物の違いを理解する
- 共晶反応・包晶反応の材料科学的意義を説明できる
- Fe-C系相図を読み、鋼の組織を予測できる
- α-γ変態(フェライト-オーステナイト変態)の熱力学を理解する
- マルテンサイト変態のメカニズムを説明できる
- TTT図・CCT図を用いて熱処理プロセスを設計できる
- 高エントロピー合金(HEA)の配置エントロピーを計算できる
📖 固溶体と金属間化合物
固溶体(Solid Solution)
2種以上の元素が結晶格子中でランダムに混合した単一相の固体
置換型固溶体: 溶質原子が溶媒原子の格子点を置換
- Hume-Rothery則: 原子半径差<15%、結晶構造同一、電気陰性度類似
- 例: Cu-Ni(全率固溶)、Fe-Cr(ステンレス鋼)
侵入型固溶体: 溶質原子が格子間隙に侵入
- 溶質原子は小さい(C, N, H, B)
- 例: Fe-C(鋼)、Ti-O
金属間化合物(Intermetallic Compound)
特定の化学量論比で形成される規則構造
- 例: Fe₃C(セメンタイト)、Ni₃Al、TiAl
- 特徴: 高強度・高脆性・高融点
💻 例題5.1: Fe-C系相図の解析
Python実装: Fe-C系相図の描画と読み方
import numpy as np
import matplotlib.pyplot as plt
def fe_c_phase_diagram():
"""Fe-C系相図の簡略モデル"""
# 組成(C wt%)
# 液相線
x_liquidus = np.array([0, 0.5, 2.11, 4.3, 6.69])
T_liquidus = np.array([1538, 1500, 1148, 1148, 1130])
# γ相(オーステナイト)固相線
x_gamma_solidus = np.array([0, 0.5, 2.11])
T_gamma_solidus = np.array([1495, 1450, 1148])
# α相(フェライト)境界
x_alpha = np.array([0, 0.022, 0.022, 0, 0])
T_alpha = np.array([912, 727, 1495, 1538, 912])
# γ相境界
x_gamma_boundary = np.array([0.022, 0.77, 2.11, 2.11, 0.77, 0.022])
T_gamma_boundary = np.array([727, 727, 1148, 1495, 1495, 1495])
# セメンタイト境界
x_cementite = np.array([6.69, 6.69])
T_cementite = np.array([727, 1130])
# 共晶点・共析点
eutectic_point = (4.3, 1148) # L → γ + Fe₃C
eutectoid_point = (0.77, 727) # γ → α + Fe₃C
return {
'liquidus': (x_liquidus, T_liquidus),
'gamma_solidus': (x_gamma_solidus, T_gamma_solidus),
'alpha': (x_alpha, T_alpha),
'gamma_boundary': (x_gamma_boundary, T_gamma_boundary),
'cementite': (x_cementite, T_cementite),
'eutectic': eutectic_point,
'eutectoid': eutectoid_point
}
# 相図の描画
phase_data = fe_c_phase_diagram()
fig, ax = plt.subplots(figsize=(12, 8))
# 液相線
x_liq, T_liq = phase_data['liquidus']
ax.plot(x_liq, T_liq, 'r-', linewidth=2.5, label='液相線')
# γ相固相線
x_g_sol, T_g_sol = phase_data['gamma_solidus']
ax.plot(x_g_sol, T_g_sol, 'b-', linewidth=2.5)
# α相境界
x_a, T_a = phase_data['alpha']
ax.plot(x_a, T_a, 'g-', linewidth=2.5, label='α相(フェライト)')
# γ相境界
x_g, T_g = phase_data['gamma_boundary']
ax.plot(x_g, T_g, 'b-', linewidth=2.5, label='γ相(オーステナイト)')
# セメンタイト境界
x_cem, T_cem = phase_data['cementite']
ax.plot([6.69], [1130], 'ko', markersize=8)
ax.axvline(6.69, color='purple', linestyle='--', linewidth=1.5,
label='Fe₃C(セメンタイト)')
# 重要点
eutectic = phase_data['eutectic']
eutectoid = phase_data['eutectoid']
ax.plot(eutectic[0], eutectic[1], 'ro', markersize=12, label=f'共晶点(C {eutectic[0]:.1f}%, {eutectic[1]}°C)')
ax.plot(eutectoid[0], eutectoid[1], 'mo', markersize=12, label=f'共析点(C {eutectoid[0]:.2f}%, {eutectoid[1]}°C)')
# 領域ラベル
ax.text(0.2, 1000, 'δ-Fe', fontsize=12, ha='center')
ax.text(0.2, 1300, 'L(液相)', fontsize=13, ha='center', fontweight='bold')
ax.text(0.5, 1000, 'γ\n(オーステナイト)', fontsize=12, ha='center')
ax.text(0.01, 850, 'α\n(フェライト)', fontsize=12, ha='center')
ax.text(0.4, 650, 'α + Fe₃C\n(パーライト)', fontsize=11, ha='center')
ax.text(3.0, 1000, 'L + γ', fontsize=11, ha='center')
ax.text(5.0, 1000, 'L + Fe₃C', fontsize=11, ha='center')
# 重要な炭素濃度を示す垂直線
ax.axvline(0.022, color='gray', linestyle=':', alpha=0.5)
ax.text(0.022, 500, '0.022%\n(α最大固溶)', fontsize=9, ha='center')
ax.axvline(0.77, color='gray', linestyle=':', alpha=0.5)
ax.text(0.77, 500, '0.77%\n(共析点)', fontsize=9, ha='center')
ax.axvline(2.11, color='gray', linestyle=':', alpha=0.5)
ax.text(2.11, 500, '2.11%\n(γ最大固溶)', fontsize=9, ha='center')
ax.set_xlabel('炭素濃度 (wt%)', fontsize=13)
ax.set_ylabel('温度 (°C)', fontsize=13)
ax.set_title('Fe-C系相図(鉄-炭素系)', fontsize=15, fontweight='bold')
ax.set_xlim([0, 7])
ax.set_ylim([400, 1600])
ax.legend(loc='upper right', fontsize=10)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('materials_fe_c_phase_diagram.png', dpi=300, bbox_inches='tight')
plt.show()
# Fe-C系の分類
print("=== Fe-C系の分類 ===\n")
print(f"{'種類':<15} {'炭素濃度 (wt%)':<20} {'主要組織':<30}")
print("-" * 65)
print(f"{'純鉄':<15} {'< 0.008':<20} {'α-Fe(フェライト)':<30}")
print(f"{'鋼(Steel)':<15} {'0.008 - 2.11':<20} {'フェライト + セメンタイト':<30}")
print(f"{' 亜共析鋼':<15} {'< 0.77':<20} {'フェライト主 + パーライト':<30}")
print(f"{' 共析鋼':<15} {'= 0.77':<20} {'パーライト(層状組織)':<30}")
print(f"{' 過共析鋼':<15} {'0.77 - 2.11':<20} {'セメンタイト + パーライト':<30}")
print(f"{'鋳鉄(Cast Iron)':<15} {'2.11 - 6.69':<20} {'γ + グラファイト/Fe₃C':<30}")
print()
print("重要な相変態温度:")
print(f" A₁: 727°C(共析温度、γ → α + Fe₃C)")
print(f" A₃: 912°C(α → γ 変態開始)")
print(f" 融点: 1538°C(純鉄)")
💻 例題5.2: α-γ変態温度の計算
α-γ変態(フェライト-オーステナイト変態)
鉄の同素変態:
\[
\text{α-Fe (BCC)} \xrightarrow{912°C} \text{γ-Fe (FCC)}
\]
相平衡条件: 化学ポテンシャルが等しい
\[
\mu^\alpha(T, P) = \mu^\gamma(T, P)
\]
Gibbs自由エネルギー差:
\[
\Delta G^{\gamma \to \alpha} = \Delta H - T \Delta S
\]
Python実装: α-γ変態の熱力学計算
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
# α-γ変態のパラメータ(純鉄)
def gibbs_alpha_gamma(T):
"""α相とγ相のGibbs自由エネルギー差
Args:
T: 温度 (K)
Returns:
ΔG^(γ→α): Gibbs自由エネルギー差 (J/mol)
"""
# 実験値に基づくモデル
# ΔH ≈ -900 J/mol, ΔS ≈ -1.0 J/(mol·K) (簡略化)
T_eq = 1185 # 912°C = 1185 K(α-γ変態点)
DH = -900 # J/mol(変態エンタルピー)
DS = DH / T_eq # J/(mol·K)
DG = DH - T * DS
return DG
# 温度範囲
T_range = np.linspace(800, 1400, 100) # K
DG_values = [gibbs_alpha_gamma(T) for T in T_range]
# 変態点の計算
T_transformation = fsolve(gibbs_alpha_gamma, 1185)[0]
# 可視化
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
# Gibbs自由エネルギー差
ax1 = axes[0]
ax1.plot(T_range - 273.15, DG_values, 'b-', linewidth=2.5)
ax1.axhline(0, color='r', linestyle='--', linewidth=2, label='ΔG = 0(平衡)')
ax1.axvline(T_transformation - 273.15, color='g', linestyle='--',
linewidth=2, label=f'変態点 {T_transformation - 273.15:.0f}°C')
# 安定相の領域
ax1.fill_between(T_range - 273.15, -2000, 0,
where=(T_range < T_transformation),
color='lightblue', alpha=0.3, label='α相安定')
ax1.fill_between(T_range - 273.15, 0, 2000,
where=(T_range > T_transformation),
color='lightcoral', alpha=0.3, label='γ相安定')
ax1.set_xlabel('Temperature (°C)')
ax1.set_ylabel('ΔG^(γ→α) (J/mol)')
ax1.set_title('α-γ変態のGibbs自由エネルギー')
ax1.legend()
ax1.grid(True, alpha=0.3)
# 炭素濃度による変態点の変化
# 簡略モデル: T_γ→α = 912°C - k·[C%]
C_range = np.linspace(0, 1.5, 50) # C wt%
k = 200 # °C/wt%(経験則)
T_gamma_alpha = 912 - k * C_range
ax2 = axes[1]
ax2.plot(C_range, T_gamma_alpha, 'r-', linewidth=2.5, label='A₃線(α-γ変態開始)')
ax2.axhline(727, color='purple', linestyle='--', linewidth=2, label='A₁線(共析温度)')
# 重要な組成
ax2.axvline(0.77, color='gray', linestyle=':', alpha=0.5)
ax2.text(0.77, 650, '共析組成\n0.77%', fontsize=10, ha='center')
# 領域ラベル
ax2.text(0.3, 850, 'γ相\n(オーステナイト)', fontsize=12, ha='center',
bbox=dict(boxstyle='round', facecolor='lightcoral', alpha=0.5))
ax2.text(0.3, 750, 'α + γ', fontsize=11, ha='center')
ax2.text(0.3, 650, 'α + Fe₃C\n(フェライト+セメンタイト)', fontsize=11, ha='center',
bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.5))
ax2.set_xlabel('炭素濃度 (wt%)')
ax2.set_ylabel('温度 (°C)')
ax2.set_title('炭素濃度とα-γ変態温度')
ax2.set_xlim([0, 1.5])
ax2.set_ylim([600, 950])
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('materials_alpha_gamma_transformation.png', dpi=300, bbox_inches='tight')
plt.show()
# 計算結果
print("=== α-γ変態の熱力学 ===\n")
print(f"変態点(計算): {T_transformation - 273.15:.2f}°C")
print(f"実験値: 912°C")
print()
print("炭素濃度による変態点降下:")
print(f"{'C濃度 (wt%)':<15} {'変態温度 (°C)':<20}")
print("-" * 35)
for C in [0, 0.2, 0.4, 0.6, 0.77]:
T = 912 - k * C
print(f"{C:<15.2f} {T:<20.0f}")
print("\n物理的意義:")
print(" - α相(BCC)は炭素固溶度が低い(0.022% at 727°C)")
print(" - γ相(FCC)は炭素固溶度が高い(2.11% at 1148°C)")
print(" - 炭素添加でγ相が安定化 → 変態温度低下")
💻 例題5.3: マルテンサイト変態の熱力学
マルテンサイト変態
無拡散型変態: γ相(FCC)から急冷により形成される過飽和固溶体
特徴:
- 拡散なし(原子の協調的剪断変形)
- 準安定相(非平衡)
- 高硬度・高脆性
- 結晶構造: BCT(体心正方格子)
Ms点(Martensite start): マルテンサイト変態開始温度
\[
M_s = 539 - 423[\text{C}] - 30.4[\text{Mn}] - 12.1[\text{Cr}] - 17.7[\text{Ni}] \quad (°C)
\]
Python実装: Ms点の計算と冷却曲線
import numpy as np
import matplotlib.pyplot as plt
def calculate_Ms(C, Mn=0, Cr=0, Ni=0):
"""マルテンサイト変態開始温度(Ms点)の計算
Andrews式による経験則
Args:
C: 炭素濃度 (wt%)
Mn: マンガン濃度 (wt%)
Cr: クロム濃度 (wt%)
Ni: ニッケル濃度 (wt%)
Returns:
Ms: マルテンサイト変態開始温度 (°C)
"""
Ms = 539 - 423*C - 30.4*Mn - 12.1*Cr - 17.7*Ni
return Ms
# 炭素濃度によるMs点の変化
C_range = np.linspace(0.1, 1.2, 50)
Ms_values = [calculate_Ms(C) for C in C_range]
# 合金元素の影響
Mn_range = [0, 1.0, 2.0]
Ni_range = [0, 2.0, 4.0]
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
# 炭素濃度の影響
ax1 = axes[0]
ax1.plot(C_range, Ms_values, 'b-', linewidth=2.5, label='Plain carbon steel')
# Mn添加の影響
for Mn in Mn_range[1:]:
Ms_Mn = [calculate_Ms(C, Mn=Mn) for C in C_range]
ax1.plot(C_range, Ms_Mn, '--', linewidth=2,
label=f'+ {Mn:.1f}% Mn')
ax1.axhline(0, color='red', linestyle=':', linewidth=1.5, label='室温')
ax1.set_xlabel('炭素濃度 (wt%)')
ax1.set_ylabel('Ms点 (°C)')
ax1.set_title('マルテンサイト変態開始温度(Ms点)')
ax1.legend()
ax1.grid(True, alpha=0.3)
ax1.set_ylim([-100, 550])
# 冷却曲線とマルテンサイト分率
ax2 = axes[1]
# Koistinen-Marburger式: f_M = 1 - exp(-α(Ms - T))
def martensite_fraction(T, Ms, alpha=0.011):
"""マルテンサイト分率
Args:
T: 温度 (°C)
Ms: Ms点 (°C)
alpha: 定数(通常 0.011)
Returns:
f_M: マルテンサイト分率
"""
if T >= Ms:
return 0
else:
f_M = 1 - np.exp(-alpha * (Ms - T))
return f_M
# 異なる炭素濃度でのマルテンサイト分率
T_range = np.linspace(-100, 800, 200)
C_values = [0.3, 0.6, 0.9]
colors = ['blue', 'green', 'red']
for C, color in zip(C_values, colors):
Ms = calculate_Ms(C)
f_M = [martensite_fraction(T, Ms) for T in T_range]
ax2.plot(T_range, f_M, color=color, linewidth=2.5,
label=f'C {C:.1f}% (Ms={Ms:.0f}°C)')
ax2.axvline(25, color='purple', linestyle='--', linewidth=1.5, label='室温')
ax2.set_xlabel('温度 (°C)')
ax2.set_ylabel('マルテンサイト分率')
ax2.set_title('マルテンサイト分率の温度依存性')
ax2.legend()
ax2.grid(True, alpha=0.3)
ax2.set_xlim([-100, 800])
ax2.set_ylim([0, 1])
plt.tight_layout()
plt.savefig('materials_martensite_transformation.png', dpi=300, bbox_inches='tight')
plt.show()
# 計算例
print("=== マルテンサイト変態のMs点 ===\n")
steels = [
("低炭素鋼", 0.2, 0, 0, 0),
("中炭素鋼", 0.6, 0, 0, 0),
("高炭素鋼", 1.0, 0, 0, 0),
("Mn鋼", 0.6, 2.0, 0, 0),
("Cr-Ni鋼", 0.6, 1.0, 12.0, 8.0),
]
print(f"{'鋼種':<15} {'C%':<6} {'Mn%':<6} {'Cr%':<6} {'Ni%':<6} {'Ms点 (°C)':<12}")
print("-" * 60)
for name, C, Mn, Cr, Ni in steels:
Ms = calculate_Ms(C, Mn, Cr, Ni)
print(f"{name:<15} {C:<6.1f} {Mn:<6.1f} {Cr:<6.1f} {Ni:<6.1f} {Ms:<12.0f}")
print("\n室温マルテンサイト分率(25°C):")
for name, C, Mn, Cr, Ni in steels:
Ms = calculate_Ms(C, Mn, Cr, Ni)
f_M = martensite_fraction(25, Ms)
print(f" {name}: {f_M*100:.1f}%")
print("\n重要な知見:")
print(" - 炭素↑ → Ms点↓(マルテンサイト形成しにくい)")
print(" - 合金元素(Mn, Cr, Ni)もMs点を下げる")
print(" - Ms < 室温の場合、残留オーステナイトが残る")
💻 例題5.4: TTT図(Time-Temperature-Transformation)の描画
TTT図とは
恒温変態図: 等温保持での変態開始・終了時間を示す
主要な変態:
- パーライト変態: 拡散型、層状組織(α + Fe₃C)
- ベイナイト変態: 中間的、針状組織
- マルテンサイト変態: 無拡散型、急冷により形成
用途: 熱処理プロセス設計、組織予測
Python実装: TTT図の模擬データ生成
import numpy as np
import matplotlib.pyplot as plt
def generate_TTT_diagram(C_content=0.8):
"""TTT図の模擬データ生成
Args:
C_content: 炭素濃度 (wt%)
Returns:
TTT diagram data
"""
# 温度範囲
T_range = np.linspace(200, 700, 100)
# パーライト変態(C曲線)
# 鼻点(最短変態時間): ~550°C, ~1秒
T_pearlite_nose = 550
t_pearlite_nose = 1.0 # 秒
def pearlite_curve(T, factor):
"""パーライト変態曲線(Johnson-Mehl-Avrami式に基づく)"""
if T < 500 or T > 727:
return 1e10 # 変態しない
else:
# C曲線の形状
t = t_pearlite_nose * factor * np.exp(abs(T - T_pearlite_nose) / 50)
return t
t_pearlite_start = [pearlite_curve(T, 1) for T in T_range]
t_pearlite_finish = [pearlite_curve(T, 10) for T in T_range]
# ベイナイト変態
T_bainite_nose = 350
t_bainite_nose = 10.0
def bainite_curve(T, factor):
if T < 250 or T > 500:
return 1e10
else:
t = t_bainite_nose * factor * np.exp(abs(T - T_bainite_nose) / 30)
return t
t_bainite_start = [bainite_curve(T, 1) for T in T_range]
t_bainite_finish = [bainite_curve(T, 10) for T in T_range]
# マルテンサイト(瞬間的)
Ms = calculate_Ms(C_content)
Mf = Ms - 215 # Mf点(マルテンサイト変態終了)
return {
'T_range': T_range,
'pearlite_start': t_pearlite_start,
'pearlite_finish': t_pearlite_finish,
'bainite_start': t_bainite_start,
'bainite_finish': t_bainite_finish,
'Ms': Ms,
'Mf': Mf
}
# TTT図の描画
C = 0.8 # 共析鋼
ttt_data = generate_TTT_diagram(C)
fig, ax = plt.subplots(figsize=(12, 8))
T = ttt_data['T_range']
t_p_s = np.array(ttt_data['pearlite_start'])
t_p_f = np.array(ttt_data['pearlite_finish'])
t_b_s = np.array(ttt_data['bainite_start'])
t_b_f = np.array(ttt_data['bainite_finish'])
# 時間を有効範囲でマスク
valid_p_s = t_p_s < 1e6
valid_p_f = t_p_f < 1e6
valid_b_s = t_b_s < 1e6
valid_b_f = t_b_f < 1e6
# パーライト
ax.semilogx(t_p_s[valid_p_s], T[valid_p_s], 'b-', linewidth=2.5, label='パーライト変態開始')
ax.semilogx(t_p_f[valid_p_f], T[valid_p_f], 'b--', linewidth=2.5, label='パーライト変態終了')
ax.fill_betweenx(T[valid_p_s], t_p_s[valid_p_s], t_p_f[valid_p_f],
where=valid_p_s & valid_p_f,
color='lightblue', alpha=0.3)
# ベイナイト
ax.semilogx(t_b_s[valid_b_s], T[valid_b_s], 'g-', linewidth=2.5, label='ベイナイト変態開始')
ax.semilogx(t_b_f[valid_b_f], T[valid_b_f], 'g--', linewidth=2.5, label='ベイナイト変態終了')
ax.fill_betweenx(T[valid_b_s], t_b_s[valid_b_s], t_b_f[valid_b_f],
where=valid_b_s & valid_b_f,
color='lightgreen', alpha=0.3)
# マルテンサイト
Ms = ttt_data['Ms']
Mf = ttt_data['Mf']
ax.axhline(Ms, color='red', linestyle='-', linewidth=2.5, label=f'Ms = {Ms:.0f}°C')
ax.axhline(Mf, color='red', linestyle='--', linewidth=2, label=f'Mf = {Mf:.0f}°C')
ax.fill_between([1e-2, 1e6], Mf, Ms, color='lightcoral', alpha=0.3)
# 冷却曲線の例
# 徐冷: パーライト形成
t_cool_slow = np.logspace(-1, 3, 50)
T_cool_slow = 900 - 100 * np.log10(t_cool_slow + 1)
ax.plot(t_cool_slow, T_cool_slow, 'purple', linewidth=2, linestyle=':',
label='徐冷(炉冷)→ パーライト')
# 急冷: マルテンサイト形成
t_cool_fast = np.logspace(-2, 0, 30)
T_cool_fast = 900 - 800 * t_cool_fast
ax.plot(t_cool_fast, T_cool_fast, 'orange', linewidth=2, linestyle=':',
label='急冷(水冷)→ マルテンサイト')
# ラベル
ax.text(10, 600, 'パーライト', fontsize=14, fontweight='bold',
bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.7))
ax.text(100, 350, 'ベイナイト', fontsize=14, fontweight='bold',
bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.7))
ax.text(0.5, Ms-50, 'マルテンサイト', fontsize=14, fontweight='bold',
bbox=dict(boxstyle='round', facecolor='lightcoral', alpha=0.7))
ax.set_xlabel('時間 (秒)', fontsize=13)
ax.set_ylabel('温度 (°C)', fontsize=13)
ax.set_title(f'TTT図(Time-Temperature-Transformation)\nC {C}% 鋼', fontsize=15, fontweight='bold')
ax.set_xlim([1e-2, 1e6])
ax.set_ylim([0, 800])
ax.legend(loc='upper right', fontsize=10)
ax.grid(True, alpha=0.3, which='both')
plt.tight_layout()
plt.savefig('materials_TTT_diagram.png', dpi=300, bbox_inches='tight')
plt.show()
print("=== TTT図の読み方 ===\n")
print("1. 縦軸: 温度(オーステナイト化温度から冷却)")
print("2. 横軸: 時間(対数スケール)")
print("3. C曲線: 変態開始・終了時間")
print()
print("組織の決定:")
print(" - 徐冷(曲線を横切る)→ パーライト")
print(" - 中速冷却 → ベイナイト")
print(" - 急冷(曲線を避けてMs以下)→ マルテンサイト")
print()
print("実用例:")
print(" - 焼入れ: 急冷してマルテンサイト(高硬度)")
print(" - 焼なまし: 徐冷してパーライト(軟化)")
print(" - 焼戻し: マルテンサイトを加熱して靭性改善")
💻 例題5.5: CCT図(Continuous Cooling Transformation)の計算
Python実装: CCT図と冷却速度
import numpy as np
import matplotlib.pyplot as plt
def generate_CCT_diagram(C_content=0.4):
"""CCT図の模擬データ(連続冷却変態図)
Args:
C_content: 炭素濃度 (wt%)
"""
# TTT図に比べて曲線が右にシフト
T_range = np.linspace(200, 750, 100)
# フェライト+パーライト変態
T_fp_nose = 600
t_fp_nose = 10.0
def fp_curve(T, factor):
if T < 500 or T > 750:
return 1e10
else:
t = t_fp_nose * factor * np.exp(abs(T - T_fp_nose) / 60)
return t
t_fp_start = [fp_curve(T, 1) for T in T_range]
t_fp_finish = [fp_curve(T, 50) for T in T_range]
# ベイナイト
T_b_nose = 400
t_b_nose = 100.0
def b_curve(T, factor):
if T < 300 or T > 550:
return 1e10
else:
t = t_b_nose * factor * np.exp(abs(T - T_b_nose) / 40)
return t
t_b_start = [b_curve(T, 1) for T in T_range]
t_b_finish = [b_curve(T, 50) for T in T_range]
# マルテンサイト
Ms = calculate_Ms(C_content)
Mf = Ms - 215
return {
'T_range': T_range,
'fp_start': t_fp_start,
'fp_finish': t_fp_finish,
'b_start': t_b_start,
'b_finish': t_b_finish,
'Ms': Ms,
'Mf': Mf
}
# 冷却曲線の生成
def cooling_curve(cooling_rate, T_start=900, T_final=25):
"""冷却曲線
Args:
cooling_rate: 冷却速度 (°C/s)
T_start: 初期温度 (°C)
T_final: 最終温度 (°C)
Returns:
t, T: 時間、温度
"""
t_total = (T_start - T_final) / cooling_rate
t = np.linspace(0, t_total, 200)
T = T_start - cooling_rate * t
T = np.maximum(T, T_final)
return t, T
# CCT図の描画
C = 0.4 # 中炭素鋼
cct_data = generate_CCT_diagram(C)
fig, ax = plt.subplots(figsize=(12, 8))
T = cct_data['T_range']
t_fp_s = np.array(cct_data['fp_start'])
t_fp_f = np.array(cct_data['fp_finish'])
t_b_s = np.array(cct_data['b_start'])
t_b_f = np.array(cct_data['b_finish'])
# 有効範囲
valid_fp_s = t_fp_s < 1e6
valid_fp_f = t_fp_f < 1e6
valid_b_s = t_b_s < 1e6
valid_b_f = t_b_f < 1e6
# フェライト+パーライト
ax.semilogx(t_fp_s[valid_fp_s], T[valid_fp_s], 'b-', linewidth=2.5, label='F+P開始')
ax.semilogx(t_fp_f[valid_fp_f], T[valid_fp_f], 'b--', linewidth=2.5, label='F+P終了')
ax.fill_betweenx(T, t_fp_s, t_fp_f, where=valid_fp_s & valid_fp_f,
color='lightblue', alpha=0.3)
# ベイナイト
ax.semilogx(t_b_s[valid_b_s], T[valid_b_s], 'g-', linewidth=2.5, label='B開始')
ax.semilogx(t_b_f[valid_b_f], T[valid_b_f], 'g--', linewidth=2.5, label='B終了')
ax.fill_betweenx(T, t_b_s, t_b_f, where=valid_b_s & valid_b_f,
color='lightgreen', alpha=0.3)
# マルテンサイト
Ms = cct_data['Ms']
Mf = cct_data['Mf']
ax.axhline(Ms, color='red', linestyle='-', linewidth=2.5, label=f'Ms = {Ms:.0f}°C')
ax.axhline(Mf, color='red', linestyle='--', linewidth=2, label=f'Mf = {Mf:.0f}°C')
# 様々な冷却速度
cooling_rates = [0.5, 5, 50, 500] # °C/s
colors = ['purple', 'orange', 'brown', 'magenta']
microstructures = ['F+P', 'F+P+B', 'B+M', 'M']
for i, (cr, color, micro) in enumerate(zip(cooling_rates, colors, microstructures)):
t_cool, T_cool = cooling_curve(cr)
ax.plot(t_cool, T_cool, color=color, linewidth=2, linestyle=':',
label=f'{cr} °C/s → {micro}')
# 臨界冷却速度の表示
ax.axvline(1, color='gray', linestyle='--', alpha=0.5)
ax.text(1, 100, '臨界冷却速度\n(この速度以上で\nマルテンサイト形成)',
fontsize=10, ha='center',
bbox=dict(boxstyle='round', facecolor='yellow', alpha=0.6))
ax.set_xlabel('時間 (秒)', fontsize=13)
ax.set_ylabel('温度 (°C)', fontsize=13)
ax.set_title(f'CCT図(Continuous Cooling Transformation)\nC {C}% 鋼', fontsize=15, fontweight='bold')
ax.set_xlim([1e-1, 1e4])
ax.set_ylim([0, 900])
ax.legend(loc='upper right', fontsize=9)
ax.grid(True, alpha=0.3, which='both')
plt.tight_layout()
plt.savefig('materials_CCT_diagram.png', dpi=300, bbox_inches='tight')
plt.show()
# 冷却速度と組織の関係
print("=== CCT図と冷却速度 ===\n")
print(f"{'冷却速度 (°C/s)':<20} {'冷却時間 (900→25°C)':<25} {'組織':<30}")
print("-" * 75)
for cr in cooling_rates:
t_total = (900 - 25) / cr
# 組織判定(簡略)
if cr < 1:
micro = "フェライト + パーライト"
elif cr < 10:
micro = "フェライト + パーライト + ベイナイト"
elif cr < 100:
micro = "ベイナイト + マルテンサイト"
else:
micro = "マルテンサイト"
print(f"{cr:<20.1f} {t_total:<25.1f} {micro:<30}")
print("\n冷却方法と冷却速度:")
print(" - 炉冷(Furnace cooling): ~0.1-1 °C/s")
print(" - 空冷(Air cooling): ~1-10 °C/s")
print(" - 油冷(Oil quenching): ~10-100 °C/s")
print(" - 水冷(Water quenching): ~100-1000 °C/s")
print()
print("TTT図 vs CCT図:")
print(" - TTT: 等温変態(実験室的)")
print(" - CCT: 連続冷却変態(実用的)")
print(" - CCT曲線はTTT曲線より右側(遅い時間)")
💻 例題5.6: 合金の混合エンタルピー計算
Python実装: 二元系の混合エンタルピー
import numpy as np
import matplotlib.pyplot as plt
def mixing_enthalpy(x_B, H_AB, omega=0):
"""二元合金A-Bの混合エンタルピー
正則溶体モデル: ΔH_mix = Ω x_A x_B
Args:
x_B: B原子分率
H_AB: 相互作用パラメータ(A-B結合エネルギー)
omega: 相互作用パラメータ Ω = z(ε_AB - (ε_AA + ε_BB)/2)
Returns:
ΔH_mix: 混合エンタルピー (J/mol)
"""
x_A = 1 - x_B
if omega == 0:
omega = H_AB
DH_mix = omega * x_A * x_B
return DH_mix
def mixing_entropy(x_B, R=8.314):
"""理想溶体の配置エントロピー
Args:
x_B: B原子分率
R: 気体定数 (J/(mol·K))
Returns:
ΔS_mix: 混合エントロピー (J/(mol·K))
"""
x_A = 1 - x_B
if x_A == 0 or x_B == 0:
return 0
else:
DS_mix = -R * (x_A * np.log(x_A) + x_B * np.log(x_B))
return DS_mix
def mixing_gibbs(x_B, T, omega, R=8.314):
"""混合Gibbs自由エネルギー
ΔG_mix = ΔH_mix - T ΔS_mix
Args:
x_B: B原子分率
T: 温度 (K)
omega: 相互作用パラメータ (J/mol)
R: 気体定数
Returns:
ΔG_mix: 混合Gibbs自由エネルギー (J/mol)
"""
DH = mixing_enthalpy(x_B, 0, omega)
DS = mixing_entropy(x_B, R)
DG = DH - T * DS
return DG
# 組成範囲
x_B_range = np.linspace(0.001, 0.999, 200)
# 相互作用パラメータ(異なる系)
omega_values = {
'理想溶体(Ω=0)': 0,
'弱い吸引(Ω=-5kJ/mol)': -5000,
'強い反発(Ω=+20kJ/mol)': 20000,
}
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 混合エンタルピー
ax1 = axes[0, 0]
for name, omega in omega_values.items():
DH_values = [mixing_enthalpy(x, 0, omega) for x in x_B_range]
ax1.plot(x_B_range, np.array(DH_values) / 1000, linewidth=2.5, label=name)
ax1.set_xlabel('組成 x_B')
ax1.set_ylabel('ΔH_mix (kJ/mol)')
ax1.set_title('混合エンタルピー')
ax1.legend()
ax1.grid(True, alpha=0.3)
ax1.axhline(0, color='black', linestyle='--', linewidth=1)
# 混合エントロピー
ax2 = axes[0, 1]
DS_values = [mixing_entropy(x) for x in x_B_range]
ax2.plot(x_B_range, DS_values, 'g-', linewidth=2.5)
ax2.set_xlabel('組成 x_B')
ax2.set_ylabel('ΔS_mix (J/(mol·K))')
ax2.set_title('混合エントロピー(理想溶体)')
ax2.grid(True, alpha=0.3)
# 混合Gibbs自由エネルギー(温度依存)
ax3 = axes[1, 0]
T_values = [300, 600, 1000, 1500]
omega_example = 20000 # 反発系
for T in T_values:
DG_values = [mixing_gibbs(x, T, omega_example) for x in x_B_range]
ax3.plot(x_B_range, np.array(DG_values) / 1000, linewidth=2.5, label=f'T = {T} K')
ax3.set_xlabel('組成 x_B')
ax3.set_ylabel('ΔG_mix (kJ/mol)')
ax3.set_title(f'混合Gibbs自由エネルギー(Ω = {omega_example/1000:.0f} kJ/mol)')
ax3.legend()
ax3.grid(True, alpha=0.3)
ax3.axhline(0, color='black', linestyle='--', linewidth=1)
# 相分離の判定(∂²ΔG/∂x² < 0 でスピノーダル)
ax4 = axes[1, 1]
T = 600
omega_spinodal = 20000
DG_values = [mixing_gibbs(x, T, omega_spinodal) for x in x_B_range]
ax4.plot(x_B_range, np.array(DG_values) / 1000, 'b-', linewidth=2.5, label='ΔG_mix')
# 接線(共通接線法で相分離組成を求める - 簡略化)
# ここでは視覚的に表示
ax4.axhline(0, color='gray', linestyle='--', linewidth=1, alpha=0.5)
ax4.text(0.5, 3, f'T = {T} K\n高温で相分離傾向', fontsize=11, ha='center',
bbox=dict(boxstyle='round', facecolor='yellow', alpha=0.6))
ax4.set_xlabel('組成 x_B')
ax4.set_ylabel('ΔG_mix (kJ/mol)')
ax4.set_title('相分離と共通接線')
ax4.legend()
ax4.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('materials_mixing_enthalpy.png', dpi=300, bbox_inches='tight')
plt.show()
# 解析
print("=== 混合エンタルピーと相安定性 ===\n")
print("相互作用パラメータ Ω の意味:")
print(" Ω < 0: A-B結合が A-A, B-B より強い → 吸引、固溶傾向")
print(" Ω = 0: 理想溶体(完全にランダム)")
print(" Ω > 0: A-B結合が弱い → 反発、相分離傾向")
print()
print("ΔG_mix = ΔH_mix - T ΔS_mix の競合:")
print(" - 低温: ΔH_mixが支配 → Ω>0なら相分離")
print(" - 高温: -TΔS_mixが支配 → エントロピー項で混合")
print()
# 臨界温度の計算(簡略化)
omega_critical = 20000
R = 8.314
T_critical = omega_critical / (2 * R) # 正則溶体の臨界温度
print(f"臨界温度(正則溶体モデル):")
print(f" T_c = Ω / (2R) = {omega_critical/1000:.0f} / (2 × 8.314)")
print(f" T_c ≈ {T_critical:.0f} K = {T_critical - 273:.0f} °C")
print(f" T > T_c: 全率固溶")
print(f" T < T_c: 相分離(ミスシビリティギャップ)")
💻 例題5.7: 高エントロピー合金(HEA)の配置エントロピー
Python実装: 多元系の配置エントロピー
import numpy as np
import matplotlib.pyplot as plt
from itertools import combinations
def configurational_entropy_multicomponent(composition, R=8.314):
"""多元系の配置エントロピー
ΔS_conf = -R Σ x_i ln(x_i)
Args:
composition: 各元素の原子分率(リスト)
R: 気体定数 (J/(mol·K))
Returns:
ΔS_conf: 配置エントロピー (J/(mol·K))
"""
x = np.array(composition)
x = x[x > 0] # ゼロを除く
if np.sum(x) != 1.0:
x = x / np.sum(x) # 規格化
DS_conf = -R * np.sum(x * np.log(x))
return DS_conf
# 代表的な高エントロピー合金(HEA)
HEAs = {
'CoCrFeMnNi(Cantor合金)': [0.2, 0.2, 0.2, 0.2, 0.2], # 等原子比5元系
'AlCoCrFeNi': [0.2, 0.2, 0.2, 0.2, 0.2],
'CoCrFeNi': [0.25, 0.25, 0.25, 0.25], # 4元系
'TiZrHfNbTa': [0.2, 0.2, 0.2, 0.2, 0.2], # 難融性HEA
}
# 伝統的合金(比較用)
traditional_alloys = {
'ステンレス鋼(SUS304)': [0.70, 0.18, 0.08, 0.04], # Fe, Cr, Ni, Mn(簡略)
'Al合金(7075)': [0.90, 0.05, 0.03, 0.02], # Al, Zn, Mg, Cu(簡略)
'真鍮(黄銅)': [0.70, 0.30], # Cu, Zn
}
print("=== 高エントロピー合金(HEA)の配置エントロピー ===\n")
print(f"{'合金':<30} {'元素数':<10} {'ΔS_conf (J/(mol·K))':<25}")
print("-" * 65)
# HEAの計算
for name, comp in HEAs.items():
n_elements = len(comp)
DS = configurational_entropy_multicomponent(comp)
print(f"{name:<30} {n_elements:<10} {DS:<25.4f}")
print("\n伝統的合金(比較):")
for name, comp in traditional_alloys.items():
n_elements = len(comp)
DS = configurational_entropy_multicomponent(comp)
print(f"{name:<30} {n_elements:<10} {DS:<25.4f}")
# 理論的最大値
R = 8.314
print("\n理論的最大値:")
for n in [2, 3, 4, 5, 6]:
DS_max = R * np.log(n)
print(f" {n}元系(等原子比): ΔS_conf = R ln({n}) = {DS_max:.4f} J/(mol·K)")
# 可視化
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
# 元素数と最大エントロピー
ax1 = axes[0]
n_range = np.arange(2, 11)
DS_max_range = R * np.log(n_range)
ax1.plot(n_range, DS_max_range, 'bo-', markersize=8, linewidth=2.5,
label='理論最大値(等原子比)')
# HEAと伝統的合金をプロット
all_alloys = {**HEAs, **traditional_alloys}
for name, comp in all_alloys.items():
n = len(comp)
DS = configurational_entropy_multicomponent(comp)
marker = 's' if name in HEAs else '^'
color = 'red' if name in HEAs else 'green'
ax1.plot(n, DS, marker, markersize=10, color=color)
ax1.plot([], [], 'rs', markersize=10, label='HEA')
ax1.plot([], [], 'g^', markersize=10, label='伝統的合金')
ax1.set_xlabel('元素数')
ax1.set_ylabel('ΔS_conf (J/(mol·K))')
ax1.set_title('配置エントロピーと元素数')
ax1.legend()
ax1.grid(True, alpha=0.3)
ax1.set_xticks(n_range)
# 組成の影響(5元系で1元素の濃度を変化)
ax2 = axes[1]
x_vary = np.linspace(0.05, 0.85, 50)
DS_vary = []
for x1 in x_vary:
# 残り4元素を等分
x_rest = (1 - x1) / 4
comp = [x1, x_rest, x_rest, x_rest, x_rest]
DS = configurational_entropy_multicomponent(comp)
DS_vary.append(DS)
ax2.plot(x_vary, DS_vary, 'b-', linewidth=2.5)
ax2.axvline(0.2, color='red', linestyle='--', linewidth=2,
label='等原子比(x=0.2)')
ax2.axhline(R * np.log(5), color='red', linestyle='--', linewidth=1.5, alpha=0.5)
ax2.set_xlabel('第1元素の原子分率 x₁')
ax2.set_ylabel('ΔS_conf (J/(mol·K))')
ax2.set_title('配置エントロピーの組成依存性(5元系)')
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('materials_HEA_entropy.png', dpi=300, bbox_inches='tight')
plt.show()
# HEAの定義
print("\n=== 高エントロピー合金(HEA)の定義 ===")
print("ΔS_conf ≥ 1.5R を満たす多元系合金")
print(f" 1.5R = 1.5 × 8.314 = {1.5*R:.4f} J/(mol·K)")
print()
print("HEAの特徴:")
print(" 1. 高い配置エントロピー → 固溶体安定化")
print(" 2. 多元系(通常5元素以上)")
print(" 3. 格子歪み効果 → 高強度")
print(" 4. カクテル効果(相乗効果)")
print()
print("応用例:")
print(" - CoCrFeMnNi: 極低温での優れた靭性")
print(" - TiZrHfNbTa: 超高温耐性(難融性HEA)")
print(" - AlCoCrFeNi: 高温強度と耐酸化性")
📚 まとめ
- 固溶体(置換型・侵入型)と金属間化合物の違いを理解
- Fe-C系相図は鋼の組織制御の基礎(共析点0.77%, 727°C)
- α-γ変態は鉄の同素変態(BCC ⇄ FCC、912°C)
- マルテンサイト変態は無拡散型の相転移(高硬度組織)
- Ms点は炭素・合金元素で低下(Andrews式)
- TTT図は等温変態、CCT図は連続冷却変態を記述
- 冷却速度により組織が制御可能(パーライト・ベイナイト・マルテンサイト)
- 混合エンタルピー(正則溶体モデル)で相安定性を評価
- 高エントロピー合金(HEA)は配置エントロピーで固溶体を安定化
💡 演習問題
- [Easy] Fe-C系で炭素濃度0.4%の鋼を800°Cから徐冷すると、どの組織が得られるか。相図を用いて説明せよ。
- [Easy] Andrews式を用いて、C 0.8%, Mn 1.0% の鋼のMs点を計算せよ。
- [Medium] Koistinen-Marburger式 \(f_M = 1 - \exp(-0.011(M_s - T))\) を用いて、Ms=350°Cの鋼を25°Cまで冷却したときのマルテンサイト分率を求めよ。
- [Medium] 正則溶体モデルで相互作用パラメータΩ=20 kJ/molの二元系の臨界温度を計算せよ。ただし \(T_c = \Omega / (2R)\) とする。
- [Hard] 5元系等原子比合金(各20%)と、主成分80%+4元素各5%の合金の配置エントロピーを計算し、どちらが高エントロピー合金の定義(ΔS ≥ 1.5R)を満たすか判定せよ。