Metal Processing and Heat Treatment
金属材料の特性は、化学組成だけでなく、加工や熱処理によって大きく変化します。本章では、塑性加工、焼鈍、焼入れ・焼戻し、時効硬化などの熱処理プロセスを学び、TTT図(Time-Temperature-Transformation)やCCT図(Continuous-Cooling-Transformation)を用いた変態挙動の理解を深めます。Pythonを用いたシミュレーションにより、熱処理条件と組織・特性の関係を定量的に解析する手法も習得します。
塑性加工は、材料に降伏応力以上の応力を加えて永久変形させ、所望の形状を得る加工法です。主要な塑性加工プロセスには以下があります:
塑性加工により、結晶粒は変形方向に伸長し、転位密度が増加します。これにより加工硬化(work hardening)が生じ、材料の強度が向上します。加工度(加工ひずみ)と強度の関係は、以下の実験式で近似されます:
ここで、\(\sigma\)は応力、\(\sigma_0\)は初期降伏応力、\(K\)は強度係数、\(\varepsilon\)はひずみ、\(n\)は加工硬化指数です。
import numpy as np
import matplotlib.pyplot as plt
def work_hardening_curve(strain, sigma_0, K, n):
"""
加工硬化曲線を計算
Parameters:
-----------
strain : array-like
ひずみ
sigma_0 : float
初期降伏応力 [MPa]
K : float
強度係数 [MPa]
n : float
加工硬化指数 (0.1-0.5)
Returns:
--------
stress : array-like
応力 [MPa]
"""
return sigma_0 + K * strain**n
# 材料パラメータ(低炭素鋼の例)
sigma_0 = 200 # MPa
K = 500 # MPa
n = 0.25 # 加工硬化指数
# ひずみ範囲
strain = np.linspace(0, 0.5, 100)
# 異なる加工硬化指数での比較
n_values = [0.1, 0.25, 0.4]
colors = ['blue', 'green', 'red']
plt.figure(figsize=(10, 6))
for n_val, color in zip(n_values, colors):
stress = work_hardening_curve(strain, sigma_0, K, n_val)
plt.plot(strain, stress, color=color, linewidth=2,
label=f'n = {n_val}')
plt.xlabel('True Strain ε', fontsize=12)
plt.ylabel('True Stress σ [MPa]', fontsize=12)
plt.title('Work Hardening Behavior (σ = σ₀ + K·εⁿ)', fontsize=14)
plt.legend(fontsize=11)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('work_hardening.png', dpi=300, bbox_inches='tight')
plt.show()
print(f"Initial yield stress: {sigma_0} MPa")
print(f"Strength coefficient K: {K} MPa")
print(f"At 20% strain (ε=0.2), stress = {work_hardening_curve(0.2, sigma_0, K, 0.25):.1f} MPa")
加工材を加熱すると、転位の再配列(回復)や新しい無ひずみ結晶粒の核生成・成長(再結晶)が生じます。再結晶温度は、融点\(T_m\)(Kelvin)の約0.3~0.5倍で、材料により異なります。再結晶により、加工硬化した材料は軟化し、延性が回復します。
焼鈍(Annealing)は、材料を適切な温度に加熱・保持後、徐冷する熱処理です。主な目的と種類:
再結晶の進行度\(X\)(変態率)は、時間\(t\)と温度\(T\)に依存し、JMA式で記述されます:
ここで、\(k\)は速度定数(アレニウス型の温度依存性)、\(n\)はアブラミ指数(核生成・成長のメカニズムに依存、通常1~4)です。
import numpy as np
import matplotlib.pyplot as plt
def jma_transformation(time, k, n):
"""
Johnson-Mehl-Avrami式による変態率計算
Parameters:
-----------
time : array-like
時間 [s]
k : float
速度定数 [1/s^n]
n : float
Avrami指数 (1-4)
Returns:
--------
X : array-like
変態率(0~1)
"""
return 1 - np.exp(-k * time**n)
# 時間範囲
time = np.logspace(-2, 4, 200) # 0.01s to 10000s
# 異なる温度でのシミュレーション(速度定数kが変化)
temps = [500, 550, 600, 650] # °C
k_values = [1e-6, 5e-6, 2e-5, 8e-5] # 高温ほど速い
n = 2.5 # Avrami指数(3次元成長)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
# 左図: 異なる温度での再結晶曲線
for temp, k in zip(temps, k_values):
X = jma_transformation(time, k, n)
ax1.semilogx(time, X * 100, linewidth=2, label=f'{temp}°C')
# 50%変態時間を計算
t_50 = (np.log(2) / k)**(1/n)
ax1.plot(t_50, 50, 'o', markersize=8)
ax1.set_xlabel('Time [s]', fontsize=12)
ax1.set_ylabel('Recrystallized Fraction [%]', fontsize=12)
ax1.set_title('Recrystallization Kinetics (JMA Model)', fontsize=14)
ax1.legend(fontsize=11)
ax1.grid(True, alpha=0.3)
ax1.set_ylim(0, 105)
# 右図: Avrami指数の影響(600°C)
n_values = [1, 2, 3, 4]
k_ref = 2e-5
for n_val in n_values:
X = jma_transformation(time, k_ref, n_val)
ax2.semilogx(time, X * 100, linewidth=2, label=f'n = {n_val}')
ax2.set_xlabel('Time [s]', fontsize=12)
ax2.set_ylabel('Recrystallized Fraction [%]', fontsize=12)
ax2.set_title('Effect of Avrami Exponent n', fontsize=14)
ax2.legend(fontsize=11)
ax2.grid(True, alpha=0.3)
ax2.set_ylim(0, 105)
plt.tight_layout()
plt.savefig('jma_recrystallization.png', dpi=300, bbox_inches='tight')
plt.show()
# 50%再結晶時間の計算例
t_50_calc = (np.log(2) / k_values[2])**(1/n)
print(f"At 600°C, 50% recrystallization time: {t_50_calc:.2f} seconds")
焼入れ(Quenching)は、鋼をオーステナイト域(A3点以上、通常850~950°C)に加熱後、急冷してマルテンサイト組織を得る熱処理です。マルテンサイトは、オーステナイトが拡散変態せず、無拡散せん断変態により生成される硬質な組織です。マルテンサイト変態開始温度\(M_s\)と終了温度\(M_f\)は、炭素含有量\(C\)(wt%)により以下の実験式で推定されます:
焼入れままのマルテンサイトは硬いが脆いため、焼戻し(Tempering)を施します。150~650°Cで加熱・保持することで、炭化物が析出し、内部応力が緩和され、靭性が向上します。焼戻し温度により、焼戻しマルテンサイト、トルースタイト、ソルバイトなど異なる組織が得られます。
import numpy as np
import matplotlib.pyplot as plt
def calculate_ms_temperature(C, Mn=0, Ni=0, Cr=0):
"""
マルテンサイト変態開始温度Msの計算(Andrews式)
Parameters:
-----------
C : float
炭素含有量 [wt%]
Mn, Ni, Cr : float
合金元素含有量 [wt%]
Returns:
--------
Ms : float
マルテンサイト変態開始温度 [°C]
"""
Ms = 539 - 423*C - 30.4*Mn - 17.7*Ni - 12.1*Cr
return Ms
def cooling_curve(time, T0, T_env, cooling_rate):
"""
冷却曲線のシミュレーション(Newton冷却則の簡易モデル)
Parameters:
-----------
time : array-like
時間 [s]
T0 : float
初期温度 [°C]
T_env : float
環境温度(冷却媒体温度) [°C]
cooling_rate : float
冷却速度パラメータ [1/s]
Returns:
--------
T : array-like
温度 [°C]
"""
return T_env + (T0 - T_env) * np.exp(-cooling_rate * time)
# 炭素鋼のMs温度計算
carbon_contents = [0.2, 0.4, 0.6, 0.8, 1.0]
print("=== Martensite Start Temperature (Ms) ===")
for C in carbon_contents:
Ms = calculate_ms_temperature(C)
print(f"C = {C:.1f} wt%: Ms = {Ms:.1f}°C")
# 冷却曲線シミュレーション
time = np.linspace(0, 100, 500) # 0-100秒
T0 = 850 # オーステナイト化温度
# 異なる冷却媒体(冷却速度が異なる)
cooling_media = {
'Water': (20, 0.08), # 水冷(速い)
'Oil': (60, 0.03), # 油冷(中間)
'Air': (25, 0.005) # 空冷(遅い)
}
plt.figure(figsize=(12, 6))
for media, (T_env, rate) in cooling_media.items():
T = cooling_curve(time, T0, T_env, rate)
plt.plot(time, T, linewidth=2, label=media)
# Ms温度線を追加(0.4%C鋼の例)
Ms_04 = calculate_ms_temperature(0.4)
plt.axhline(y=Ms_04, color='red', linestyle='--', linewidth=2,
label=f'Ms (0.4%C) = {Ms_04:.0f}°C')
# A1温度線(約727°C、フェライト+パーライト変態開始)
plt.axhline(y=727, color='orange', linestyle='--', linewidth=2,
label='A1 = 727°C')
plt.xlabel('Time [s]', fontsize=12)
plt.ylabel('Temperature [°C]', fontsize=12)
plt.title('Cooling Curves for Different Quenching Media', fontsize=14)
plt.legend(fontsize=11)
plt.grid(True, alpha=0.3)
plt.xlim(0, 100)
plt.ylim(0, 900)
plt.tight_layout()
plt.savefig('cooling_curves.png', dpi=300, bbox_inches='tight')
plt.show()
# 臨界冷却速度の評価
print("\n=== Cooling Rate Analysis ===")
for media, (T_env, rate) in cooling_media.items():
T_at_10s = cooling_curve(10, T0, T_env, rate)
avg_rate = (T0 - T_at_10s) / 10
print(f"{media}: Average cooling rate (0-10s) = {avg_rate:.1f}°C/s")
焼入れ性とは、焼入れにより硬化する能力(深さ)を示す指標です。材料の化学組成や結晶粒径により決まり、Jominy試験(一端焼入れ試験)で評価されます。合金元素(Mn, Cr, Mo, Niなど)の添加により焼入れ性が向上します。
時効硬化(Age Hardening, Precipitation Hardening)は、Al合金やステンレス鋼などで用いられる析出強化熱処理です。プロセスは以下の3段階で構成されます:
析出物が転位の運動を妨げることで、強度が向上します(Orowan機構、Chapter 3参照)。時効時間により、ピーク時効(最大硬度)と過時効(硬度低下)が生じます。
import numpy as np
import matplotlib.pyplot as plt
def age_hardening_curve(time, H0, H_max, k_peak, k_over, t_peak):
"""
時効硬化曲線のモデル化(簡易的な経験式)
Parameters:
-----------
time : array-like
時効時間 [hours]
H0 : float
初期硬度(焼入れまま) [HV]
H_max : float
最大硬度(ピーク時効) [HV]
k_peak : float
硬化速度パラメータ
k_over : float
過時効軟化速度パラメータ
t_peak : float
ピーク時効時間 [hours]
Returns:
--------
hardness : array-like
硬度 [HV]
"""
# ピーク時効までの硬化
H_peak = H0 + (H_max - H0) * (1 - np.exp(-k_peak * time))
# 過時効による軟化
H_over = H_max - (H_max - H0) * 0.3 * (1 - np.exp(-k_over * (time - t_peak)))
# 時間によって切り替え
hardness = np.where(time < t_peak, H_peak, H_over)
return hardness
# Al-Cu合金(2024系)の時効硬化シミュレーション
time = np.logspace(-1, 3, 300) # 0.1~1000時間
# 異なる時効温度でのシミュレーション
aging_temps = [150, 175, 200] # °C
colors = ['blue', 'green', 'red']
# 温度が高いほど速く硬化するが、ピーク硬度は低下
params = {
150: {'H0': 70, 'H_max': 140, 'k_peak': 0.05, 'k_over': 0.01, 't_peak': 50},
175: {'H0': 70, 'H_max': 135, 'k_peak': 0.15, 'k_over': 0.03, 't_peak': 15},
200: {'H0': 70, 'H_max': 125, 'k_peak': 0.30, 'k_over': 0.08, 't_peak': 5}
}
plt.figure(figsize=(12, 6))
for temp, color in zip(aging_temps, colors):
p = params[temp]
hardness = age_hardening_curve(time, p['H0'], p['H_max'],
p['k_peak'], p['k_over'], p['t_peak'])
plt.semilogx(time, hardness, color=color, linewidth=2,
label=f'{temp}°C (Peak: {p["H_max"]} HV at {p["t_peak"]}h)')
# ピーク時効点をマーク
plt.plot(p['t_peak'], p['H_max'], 'o', color=color, markersize=10)
# 自然時効(室温、25°C)の追加
natural_aging = 70 + (95 - 70) * (1 - np.exp(-0.005 * time))
plt.semilogx(time, natural_aging, 'k--', linewidth=2,
label='Natural Aging (25°C)')
plt.xlabel('Aging Time [hours]', fontsize=12)
plt.ylabel('Hardness [HV]', fontsize=12)
plt.title('Age Hardening Curves for Al-Cu Alloy (2024)', fontsize=14)
plt.legend(fontsize=10)
plt.grid(True, alpha=0.3)
plt.xlim(0.1, 1000)
plt.ylim(60, 150)
plt.tight_layout()
plt.savefig('age_hardening.png', dpi=300, bbox_inches='tight')
plt.show()
# T6処理(溶体化+人工時効)の推奨条件
print("=== Recommended T6 Heat Treatment ===")
print("Solution Treatment: 495-505°C, 1-2 hours")
print("Quenching: Water (rapid cooling to RT)")
print("Aging: 175-190°C, 8-12 hours")
print(f"Expected Peak Hardness: ~135 HV (at 175°C, 15 hours)")
Al-Cu系では、GP zone(球状、数nm) → θ''(針状) → θ'(板状) → θ(平衡相、Al2Cu)の順に析出物が成長します。最大強度は、θ''やθ'の微細析出物が高密度に分散した状態(ピーク時効)で得られます。過時効では、析出物が粗大化し、粒子間隔が広がるため、強度が低下します。
TTT図は、オーステナイトを一定温度に保持した際の変態の開始と終了時間を示した図です。鋼の種類により、パーライト変態曲線(高温側)とベイナイト変態曲線(低温側)が現れ、最も変態速度が速い温度(nose temperature)が存在します。Ms線より下では、マルテンサイト変態が生じます。
CCT図は、連続冷却時の変態挙動を示した図で、実際の熱処理により近い条件を表します。TTT図と比較して、変態曲線は低温・長時間側にシフトします。冷却曲線がCCT図上の変態曲線と交わる点で、その組織が生成されます。
import numpy as np
import matplotlib.pyplot as plt
def ttt_curve_pearlite(time):
"""
パーライト変態曲線(簡易モデル)
Parameters:
-----------
time : array-like
時間 [s]
Returns:
--------
T_start, T_end : array-like
変態開始・終了温度 [°C]
"""
# C字型カーブのモデル化(実験的フィット)
t_nose = 1 # ノーズ位置の時間(秒)
T_nose = 550 # ノーズ温度(°C)
# 変態開始曲線
T_start = T_nose + 150 * (np.log10(time / t_nose))**2
T_start = np.clip(T_start, 400, 727)
# 変態終了曲線(開始より右側)
T_end = T_nose + 150 * (np.log10(time / (t_nose * 10)))**2
T_end = np.clip(T_end, 400, 727)
return T_start, T_end
def ttt_curve_bainite(time):
"""
ベイナイト変態曲線(簡易モデル)
"""
t_nose = 10
T_nose = 350
T_start = T_nose + 80 * (np.log10(time / t_nose))**2
T_start = np.clip(T_start, 250, 500)
T_end = T_nose + 80 * (np.log10(time / (t_nose * 10)))**2
T_end = np.clip(T_end, 250, 500)
return T_start, T_end
# 時間範囲(対数スケール)
time = np.logspace(-1, 5, 200) # 0.1s to 100000s
# TTT曲線の計算
P_start, P_end = ttt_curve_pearlite(time)
B_start, B_end = ttt_curve_bainite(time)
# Ms温度(マルテンサイト変態開始)
Ms = 350 # 0.4%C鋼の例
# TTT図の作成
fig, ax = plt.subplots(figsize=(12, 8))
# パーライト変態領域
ax.fill_betweenx(P_start, time, 1e5, alpha=0.3, color='orange',
label='Austenite')
ax.fill_betweenx(P_start, time, time * 0 + 0.1, alpha=0.4, color='yellow',
where=(P_start > 400), label='Pearlite Region')
# パーライト変態曲線
ax.semilogx(time, P_start, 'r-', linewidth=2, label='Pearlite Start')
ax.semilogx(time, P_end, 'r--', linewidth=2, label='Pearlite End')
# ベイナイト変態曲線
ax.semilogx(time, B_start, 'b-', linewidth=2, label='Bainite Start')
ax.semilogx(time, B_end, 'b--', linewidth=2, label='Bainite End')
# マルテンサイト変態線
ax.axhline(y=Ms, color='green', linestyle='-', linewidth=2.5,
label=f'Ms = {Ms}°C (Martensite)')
ax.axhline(y=Ms - 150, color='green', linestyle='--', linewidth=2,
label=f'Mf = {Ms-150}°C')
# 冷却曲線の例(急冷・徐冷)
time_cool = np.logspace(-1, 3, 100)
T_quench = 850 - 800 * (1 - np.exp(-0.05 * time_cool)) # 水冷
T_slow = 850 - 820 * (1 - np.exp(-0.0005 * time_cool)) # 炉冷
ax.semilogx(time_cool, T_quench, 'k-', linewidth=2.5,
label='Quench (Water)', alpha=0.7)
ax.semilogx(time_cool, T_slow, 'k--', linewidth=2.5,
label='Slow Cool (Furnace)', alpha=0.7)
ax.set_xlabel('Time [s]', fontsize=13)
ax.set_ylabel('Temperature [°C]', fontsize=13)
ax.set_title('TTT Diagram for Eutectoid Steel (0.8% C)', fontsize=15, fontweight='bold')
ax.legend(fontsize=10, loc='upper right')
ax.grid(True, alpha=0.3, which='both')
ax.set_xlim(0.1, 1e5)
ax.set_ylim(0, 900)
# A1温度線
ax.axhline(y=727, color='purple', linestyle=':', linewidth=1.5, alpha=0.5)
ax.text(1e4, 735, 'A1 (727°C)', fontsize=10, color='purple')
plt.tight_layout()
plt.savefig('ttt_diagram.png', dpi=300, bbox_inches='tight')
plt.show()
print("=== TTT Diagram Interpretation ===")
print("Water quench: Crosses below Ms → Full martensite")
print("Furnace cool: Passes through pearlite region → Ferrite + Pearlite")
print("Oil quench (intermediate): May produce bainite or mixed structure")
完全なマルテンサイト組織を得るために必要な最小冷却速度を臨界冷却速度と呼びます。CCT図上で、冷却曲線がパーライト・ベイナイト変態曲線に接しない最小の冷却速度です。焼入れ性が高い鋼ほど、臨界冷却速度は小さくなります。
問題: 低炭素鋼の引張試験で、真ひずみ\(\varepsilon = 0.1\)で真応力\(\sigma = 300\) MPa、\(\varepsilon = 0.3\)で\(\sigma = 420\) MPaが得られました。加工硬化式\(\sigma = K \varepsilon^n\)の\(K\)と\(n\)を求めてください(初期降伏応力\(\sigma_0\)は無視できるとします)。
import numpy as np
from scipy.optimize import curve_fit
# 実験データ
strain_exp = np.array([0.1, 0.3])
stress_exp = np.array([300, 420])
# 加工硬化モデル(σ = K * ε^n)
def work_hardening_model(strain, K, n):
return K * strain**n
# 非線形最小二乗法でパラメータフィット
params, covariance = curve_fit(work_hardening_model, strain_exp, stress_exp,
p0=[500, 0.3])
K_fit, n_fit = params
print("=== Work Hardening Parameter Fitting ===")
print(f"Strength coefficient K = {K_fit:.1f} MPa")
print(f"Work hardening exponent n = {n_fit:.3f}")
# 検証: フィット曲線と実験値の比較
stress_fit = work_hardening_model(strain_exp, K_fit, n_fit)
print("\n=== Verification ===")
for i in range(len(strain_exp)):
print(f"ε = {strain_exp[i]:.1f}: Experimental σ = {stress_exp[i]} MPa, "
f"Fitted σ = {stress_fit[i]:.1f} MPa")
# 代数的解法(2点から計算)
# σ1 = K * ε1^n, σ2 = K * ε2^n
# σ2/σ1 = (ε2/ε1)^n → n = log(σ2/σ1) / log(ε2/ε1)
n_algebraic = np.log(stress_exp[1] / stress_exp[0]) / np.log(strain_exp[1] / strain_exp[0])
K_algebraic = stress_exp[0] / (strain_exp[0]**n_algebraic)
print("\n=== Algebraic Solution (2-point method) ===")
print(f"n = log({stress_exp[1]}/{stress_exp[0]}) / log({strain_exp[1]}/{strain_exp[0]}) = {n_algebraic:.3f}")
print(f"K = {stress_exp[0]} / {strain_exp[0]}^{n_algebraic:.3f} = {K_algebraic:.1f} MPa")
# 応力予測(ε = 0.5での値)
strain_pred = 0.5
stress_pred = work_hardening_model(strain_pred, K_fit, n_fit)
print(f"\n=== Prediction ===")
print(f"At ε = {strain_pred}, predicted σ = {stress_pred:.1f} MPa")
期待される出力:
Strength coefficient K ≈ 530-550 MPa Work hardening exponent n ≈ 0.18-0.20
解説: 2点のデータから、対数を取って連立方程式を解くか、curve_fitで最小二乗フィッティングを行います。\(n\)値が小さい(0.2程度)場合、加工硬化しにくい材料(低炭素鋼など)を示します。
問題: 銅(Cu)の融点は1085°C(1358 K)です。再結晶温度が融点(K)の約0.4倍であると仮定して、再結晶温度を摂氏で求めてください。また、200°Cで応力除去焼鈍を行った場合、再結晶が生じるか判断してください。
# 銅の融点
T_m_Cu_K = 1358 # Kelvin
T_m_Cu_C = 1085 # Celsius
# 再結晶温度の推定(T_rex ≈ 0.4 * T_m)
T_rex_K = 0.4 * T_m_Cu_K
T_rex_C = T_rex_K - 273.15
print("=== Recrystallization Temperature Estimation ===")
print(f"Melting point of Cu: {T_m_Cu_K} K ({T_m_Cu_C}°C)")
print(f"Estimated recrystallization temperature: {T_rex_K:.0f} K ({T_rex_C:.0f}°C)")
# 応力除去焼鈍温度での判定
stress_relief_temp = 200 # °C
print(f"\n=== Heat Treatment at {stress_relief_temp}°C ===")
if stress_relief_temp < T_rex_C:
print(f"Temperature ({stress_relief_temp}°C) < T_rex ({T_rex_C:.0f}°C)")
print("→ Recovery occurs, but NO recrystallization")
print("→ Stress relief annealing (residual stress reduction)")
else:
print(f"Temperature ({stress_relief_temp}°C) ≥ T_rex ({T_rex_C:.0f}°C)")
print("→ Recrystallization occurs")
print("→ New strain-free grains form, material softens")
# 実用的な熱処理温度範囲
print("\n=== Practical Heat Treatment Ranges for Cu ===")
print(f"Stress relief: {T_rex_C * 0.5:.0f}-{T_rex_C * 0.8:.0f}°C (recovery only)")
print(f"Recrystallization annealing: {T_rex_C:.0f}-{T_rex_C * 1.3:.0f}°C (softening)")
print(f"Homogenization: {T_m_Cu_C * 0.8:.0f}-{T_m_Cu_C * 0.95:.0f}°C (segregation removal)")
期待される出力:
Estimated recrystallization temperature: 543 K (270°C) At 200°C: Recovery occurs, but NO recrystallization
解説: 再結晶温度は材料により異なりますが、融点の0.3~0.5倍が目安です。銅の場合、約270°C以上で再結晶が生じます。200°Cでは回復(転位の再配列)のみで、結晶粒の再生成は起こりません。
問題: 炭素鋼(C: 0.6 wt%, Mn: 0.8 wt%, Ni: 0, Cr: 0)をオーステナイト化後、水冷(室温20°Cまで急冷)しました。Ms温度を計算し、得られる組織を予測してください。また、この鋼を油冷(60°Cまで冷却後、徐冷)した場合の組織変化を考察してください。
import numpy as np
def calculate_ms_temperature(C, Mn=0, Ni=0, Cr=0):
"""
マルテンサイト変態開始温度Msの計算(Andrews式)
Ms = 539 - 423*C - 30.4*Mn - 17.7*Ni - 12.1*Cr
"""
Ms = 539 - 423*C - 30.4*Mn - 17.7*Ni - 12.1*Cr
return Ms
# 鋼の化学組成
C_content = 0.6 # wt%
Mn_content = 0.8 # wt%
Ni_content = 0
Cr_content = 0
# Ms温度の計算
Ms_temp = calculate_ms_temperature(C_content, Mn_content, Ni_content, Cr_content)
print("=== Steel Composition ===")
print(f"C: {C_content} wt%, Mn: {Mn_content} wt%, Ni: {Ni_content} wt%, Cr: {Cr_content} wt%")
print(f"\n=== Martensite Start Temperature ===")
print(f"Ms = 539 - 423×{C_content} - 30.4×{Mn_content} - 17.7×{Ni_content} - 12.1×{Cr_content}")
print(f"Ms = {Ms_temp:.1f}°C")
# Mf温度の推定(経験的にMs - 215°C)
Mf_temp = Ms_temp - 215
print(f"Mf (estimated) ≈ {Mf_temp:.1f}°C")
# 水冷の場合
quench_temp_water = 20 # °C
print(f"\n=== Water Quenching (to {quench_temp_water}°C) ===")
if quench_temp_water < Ms_temp:
martensite_fraction = 100 # 完全マルテンサイト(簡易推定)
print(f"Final temperature ({quench_temp_water}°C) < Ms ({Ms_temp:.1f}°C)")
print(f"→ Martensite transformation occurs during quenching")
print(f"→ Expected structure: ~{martensite_fraction:.0f}% Martensite (high hardness)")
print(f"→ Hardness: ~60-65 HRC (extremely hard but brittle)")
else:
print(f"Final temperature ({quench_temp_water}°C) ≥ Ms ({Ms_temp:.1f}°C)")
print(f"→ Austenite retained (not recommended)")
# 油冷の場合
quench_temp_oil = 60 # °C
print(f"\n=== Oil Quenching (to {quench_temp_oil}°C, then slow cooling) ===")
if quench_temp_oil < Ms_temp:
# 油冷は水冷より遅いため、一部パーライト/ベイナイト変態の可能性
print(f"Cooling rate: Slower than water quenching")
print(f"→ Possible pearlite/bainite transformation at higher temperatures")
print(f"→ Final structure: Martensite + Bainite (mixed)")
print(f"→ Hardness: ~50-55 HRC (slightly lower than water quench)")
print(f"→ Better toughness than full martensite")
else:
print(f"Final temperature ({quench_temp_oil}°C) ≥ Ms ({Ms_temp:.1f}°C)")
print(f"→ Austenite may transform to pearlite/bainite")
# 推奨熱処理
print(f"\n=== Recommended Heat Treatment ===")
print(f"1. Austenitizing: 820-850°C, 30-60 min")
print(f"2. Quenching: Oil quench (to avoid cracking)")
print(f"3. Tempering: 200-400°C, 1-2 hours")
print(f" → Reduces brittleness, improves toughness")
print(f" → Hardness after tempering: ~45-55 HRC")
# Ms温度への合金元素の影響
print(f"\n=== Effect of Alloying Elements on Ms ===")
elements = {'C': -423, 'Mn': -30.4, 'Ni': -17.7, 'Cr': -12.1}
for elem, coeff in elements.items():
print(f"{elem}: {coeff:.1f}°C per wt% (negative = lowers Ms)")
期待される出力:
Ms ≈ 261°C Mf ≈ 46°C Water quenching: ~100% Martensite (high hardness, brittle) Oil quenching: Martensite + Bainite (mixed, better toughness)
解説: C 0.6%鋼のMs温度は約260°Cで、室温まで冷却すればマルテンサイトが形成されます。水冷は急冷のためほぼ完全マルテンサイトですが、油冷では冷却速度が遅く、一部ベイナイトが生成される可能性があります。焼入れ後は必ず焼戻しを行い、靭性を向上させることが重要です。
問題: ある金属を600°Cで焼鈍した際、JMA式\(X = 1 - \exp(-kt^n)\)に従い、\(k = 0.01\) (1/min^n)、\(n = 2.5\)でした。50%再結晶に要する時間\(t_{50}\)を計算してください。また、90%再結晶に要する時間\(t_{90}\)も求めてください。
import numpy as np
import matplotlib.pyplot as plt
def calculate_jma_time(X_target, k, n):
"""
JMA式からターゲット変態率に到達する時間を計算
X = 1 - exp(-k*t^n)
→ t = (ln(1/(1-X)) / k)^(1/n)
Parameters:
-----------
X_target : float
目標変態率(0~1)
k : float
速度定数 [1/min^n]
n : float
Avrami指数
Returns:
--------
t : float
時間 [min]
"""
if X_target >= 1.0:
return np.inf
t = (np.log(1 / (1 - X_target)) / k)**(1 / n)
return t
# パラメータ
k = 0.01 # 1/min^n
n = 2.5 # Avrami指数
# 50%再結晶時間
X_50 = 0.5
t_50 = calculate_jma_time(X_50, k, n)
# 90%再結晶時間
X_90 = 0.9
t_90 = calculate_jma_time(X_90, k, n)
print("=== JMA Recrystallization Kinetics ===")
print(f"Parameters: k = {k} (1/min^{n}), n = {n}")
print(f"\n=== Calculation Results ===")
print(f"50% recrystallization time (t_50):")
print(f" t_50 = (ln(1/(1-{X_50})) / {k})^(1/{n})")
print(f" t_50 = (ln(2) / {k})^(1/{n})")
print(f" t_50 = {t_50:.2f} minutes ({t_50/60:.2f} hours)")
print(f"\n90% recrystallization time (t_90):")
print(f" t_90 = (ln(1/(1-{X_90})) / {k})^(1/{n})")
print(f" t_90 = (ln(10) / {k})^(1/{n})")
print(f" t_90 = {t_90:.2f} minutes ({t_90/60:.2f} hours)")
# 時間の比較
ratio = t_90 / t_50
print(f"\n=== Time Ratio ===")
print(f"t_90 / t_50 = {ratio:.2f}")
print(f"→ 90% recrystallization takes {ratio:.2f}× longer than 50%")
# 再結晶曲線のプロット
time = np.linspace(0, t_90 * 1.5, 200)
X = 1 - np.exp(-k * time**n)
plt.figure(figsize=(10, 6))
plt.plot(time, X * 100, 'b-', linewidth=2, label='Recrystallization Curve')
plt.axhline(y=50, color='green', linestyle='--', linewidth=1.5, label=f't_50 = {t_50:.1f} min')
plt.axvline(x=t_50, color='green', linestyle='--', linewidth=1.5, alpha=0.5)
plt.axhline(y=90, color='red', linestyle='--', linewidth=1.5, label=f't_90 = {t_90:.1f} min')
plt.axvline(x=t_90, color='red', linestyle='--', linewidth=1.5, alpha=0.5)
plt.plot(t_50, 50, 'go', markersize=10)
plt.plot(t_90, 90, 'ro', markersize=10)
plt.xlabel('Time [minutes]', fontsize=12)
plt.ylabel('Recrystallized Fraction [%]', fontsize=12)
plt.title(f'JMA Recrystallization Curve (k={k}, n={n})', fontsize=14)
plt.legend(fontsize=11)
plt.grid(True, alpha=0.3)
plt.xlim(0, time[-1])
plt.ylim(0, 100)
plt.tight_layout()
plt.savefig('jma_calculation.png', dpi=300, bbox_inches='tight')
plt.show()
# 異なる変態率での時間計算
print("\n=== Time for Various Recrystallization Fractions ===")
X_values = [0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99]
for X in X_values:
t = calculate_jma_time(X, k, n)
print(f"X = {X*100:5.1f}% → t = {t:7.2f} min ({t/60:5.2f} hours)")
期待される出力:
t_50 ≈ 5.28 minutes (0.09 hours) t_90 ≈ 13.00 minutes (0.22 hours) t_90 / t_50 ≈ 2.46
解説: JMA式から時間を逆算するには、\(t = [\ln(1/(1-X)) / k]^{1/n}\)を用います。50%変態(\(\ln 2\))から90%変態(\(\ln 10\))への時間比は、Avrami指数に依存します。\(n = 2.5\)の場合、約2.46倍の時間がかかります。
問題: Al-Cu合金(2024系)の時効硬化処理において、150°C、175°C、200°Cの3条件で時効処理を行いました。以下のデータから、最大硬度とそれに到達する時間を求め、最適な時効条件を推奨してください。
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
# 実験データ
data = {
150: {'time': [10, 50, 200], 'hardness': [120, 140, 135]},
175: {'time': [3, 15, 50], 'hardness': [120, 135, 125]},
200: {'time': [1, 5, 20], 'hardness': [115, 125, 115]}
}
# 最大硬度とピーク時間の決定
print("=== Age Hardening Analysis ===")
print(f"{'Temp [°C]':<12} {'Max Hardness [HV]':<20} {'Peak Time [h]':<15}")
print("-" * 50)
results = {}
for temp, values in data.items():
times = np.array(values['time'])
hardness = np.array(values['hardness'])
max_hardness = np.max(hardness)
peak_time = times[np.argmax(hardness)]
results[temp] = {'max_hardness': max_hardness, 'peak_time': peak_time}
print(f"{temp:<12} {max_hardness:<20} {peak_time:<15}")
# 推奨条件の決定
print("\n=== Recommendation ===")
best_temp = max(results, key=lambda x: results[x]['max_hardness'])
print(f"Best temperature: {best_temp}°C")
print(f"Maximum hardness: {results[best_temp]['max_hardness']} HV")
print(f"Time to peak: {results[best_temp]['peak_time']} hours")
# 実用的な推奨(生産性も考慮)
print("\n=== Practical Recommendation (T6 Treatment) ===")
print(f"Option 1 (Maximum hardness): {best_temp}°C, {results[best_temp]['peak_time']} hours")
print(f" → Highest hardness ({results[best_temp]['max_hardness']} HV)")
print(f" → Suitable for maximum strength applications")
print(f"\nOption 2 (Balanced): 175°C, 15 hours")
print(f" → Good hardness (135 HV, ~96% of max)")
print(f" → Shorter processing time (3.3× faster than 150°C)")
print(f" → Better productivity")
print(f"\nOption 3 (Rapid): 200°C, 5 hours")
print(f" → Moderate hardness (125 HV, ~89% of max)")
print(f" → Very fast processing (10× faster than 150°C)")
print(f" → Suitable for rapid production")
# 時効硬化曲線のプロット
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))
# 左図: 実験データと補間曲線
colors = {150: 'blue', 175: 'green', 200: 'red'}
for temp, values in data.items():
times = np.array(values['time'])
hardness = np.array(values['hardness'])
# 補間(cubic spline)
time_interp = np.linspace(times[0], times[-1], 100)
f_interp = interp1d(times, hardness, kind='quadratic', fill_value='extrapolate')
hardness_interp = f_interp(time_interp)
ax1.plot(time_interp, hardness_interp, color=colors[temp], linewidth=2,
label=f'{temp}°C', alpha=0.7)
ax1.plot(times, hardness, 'o', color=colors[temp], markersize=8)
# ピーク点をマーク
peak_idx = np.argmax(hardness)
ax1.plot(times[peak_idx], hardness[peak_idx], '*', color=colors[temp],
markersize=15, markeredgecolor='black', markeredgewidth=1)
ax1.set_xlabel('Aging Time [hours]', fontsize=12)
ax1.set_ylabel('Hardness [HV]', fontsize=12)
ax1.set_title('Age Hardening Curves for Al-Cu Alloy', fontsize=14)
ax1.legend(fontsize=11)
ax1.grid(True, alpha=0.3)
ax1.set_xscale('log')
# 右図: 最大硬度と到達時間の関係
temps_list = sorted(results.keys())
max_hardness_list = [results[t]['max_hardness'] for t in temps_list]
peak_time_list = [results[t]['peak_time'] for t in temps_list]
ax2_twin = ax2.twinx()
ax2.plot(temps_list, max_hardness_list, 'bo-', linewidth=2, markersize=10,
label='Max Hardness')
ax2_twin.plot(temps_list, peak_time_list, 'rs-', linewidth=2, markersize=10,
label='Peak Time')
ax2.set_xlabel('Aging Temperature [°C]', fontsize=12)
ax2.set_ylabel('Maximum Hardness [HV]', fontsize=12, color='blue')
ax2_twin.set_ylabel('Time to Peak [hours]', fontsize=12, color='red')
ax2.tick_params(axis='y', labelcolor='blue')
ax2_twin.tick_params(axis='y', labelcolor='red')
ax2.set_title('Temperature vs. Max Hardness & Peak Time', fontsize=14)
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('age_hardening_analysis.png', dpi=300, bbox_inches='tight')
plt.show()
# 過時効の評価
print("\n=== Over-aging Analysis ===")
for temp in [150, 175, 200]:
hardness_data = data[temp]['hardness']
if hardness_data[-1] < max(hardness_data):
loss = max(hardness_data) - hardness_data[-1]
loss_pct = (loss / max(hardness_data)) * 100
print(f"{temp}°C: Over-aging detected (loss = {loss} HV, {loss_pct:.1f}%)")
else:
print(f"{temp}°C: No over-aging in observed time range")
期待される出力:
Best temperature: 150°C (Max hardness: 140 HV at 50 hours) Practical recommendation: 175°C, 15 hours (135 HV, faster processing) Over-aging detected at all temperatures (hardness decreases after peak)
解説: 低温(150°C)ほど最大硬度は高いですが、到達時間が長くなります。実用的には、175°C・15時間が硬度(135 HV)と生産性のバランスが良い条件です。長時間保持すると過時効により硬度が低下するため、適切な時効時間の管理が重要です。
問題: 共析鋼(0.8% C)を850°Cから以下の冷却条件で処理した際、得られる組織を予測してください。TTT図上で、パーライト変態のノーズ温度が550°C・1秒、ベイナイト変態のノーズ温度が350°C・10秒、Ms温度が220°Cであるとします。
(a) 1秒で550°Cまで冷却後、550°Cで10秒保持
(b) 0.1秒で200°Cまで急冷
(c) 10秒で350°Cまで冷却後、350°Cで100秒保持
import numpy as np
import matplotlib.pyplot as plt
# TTT図のパラメータ
Ms_temp = 220 # マルテンサイト変態開始温度 [°C]
pearlite_nose = {'temp': 550, 'time': 1} # パーライトノーズ [°C, s]
bainite_nose = {'temp': 350, 'time': 10} # ベイナイトノーズ [°C, s]
# 冷却シナリオ
scenarios = {
'a': {'cool_time': 1, 'cool_to': 550, 'hold_temp': 550, 'hold_time': 10},
'b': {'cool_time': 0.1, 'cool_to': 200, 'hold_temp': None, 'hold_time': 0},
'c': {'cool_time': 10, 'cool_to': 350, 'hold_temp': 350, 'hold_time': 100}
}
def predict_structure(scenario_name, scenario):
"""
TTT図に基づいて組織を予測
"""
print(f"\n=== Scenario {scenario_name.upper()} ===")
print(f"Cooling: {scenario['cool_time']}s to {scenario['cool_to']}°C")
if scenario['hold_temp']:
print(f"Holding: {scenario['hold_temp']}°C for {scenario['hold_time']}s")
cool_time = scenario['cool_time']
cool_to = scenario['cool_to']
hold_temp = scenario['hold_temp']
hold_time = scenario['hold_time']
# 冷却中の変態判定
if cool_to == pearlite_nose['temp'] and cool_time >= pearlite_nose['time']:
print(f"→ Crosses pearlite nose during cooling")
print(f"→ Partial pearlite transformation likely")
partial_pearlite = True
else:
partial_pearlite = False
# 保持中の変態判定
if hold_temp == pearlite_nose['temp'] and hold_time >= pearlite_nose['time']:
print(f"→ Isothermal holding at pearlite nose temperature")
print(f"→ COMPLETE pearlite transformation")
structure = "100% Pearlite"
hardness = "~20-25 HRC (soft, ductile)"
elif hold_temp == bainite_nose['temp'] and hold_time >= bainite_nose['time']:
print(f"→ Isothermal holding at bainite nose temperature")
print(f"→ COMPLETE bainite transformation")
structure = "100% Bainite"
hardness = "~40-50 HRC (moderate hardness, good toughness)"
elif cool_to < Ms_temp and hold_temp is None:
print(f"→ Rapid cooling below Ms ({Ms_temp}°C)")
print(f"→ Martensite transformation")
structure = "~100% Martensite"
hardness = "~63-65 HRC (very hard, brittle)"
else:
print(f"→ Intermediate cooling")
if partial_pearlite:
structure = "Pearlite + Martensite (mixed)"
hardness = "~35-45 HRC"
else:
structure = "Bainite + Martensite (mixed)"
hardness = "~50-55 HRC"
print(f"\n【Predicted Structure】: {structure}")
print(f"【Expected Hardness】: {hardness}")
return structure, hardness
# 各シナリオの解析
results = {}
for name, scenario in scenarios.items():
structure, hardness = predict_structure(name, scenario)
results[name] = {'structure': structure, 'hardness': hardness}
# 結果の比較表
print("\n" + "="*70)
print("=== SUMMARY: Structure Prediction Results ===")
print("="*70)
print(f"{'Scenario':<12} {'Structure':<35} {'Hardness':<20}")
print("-"*70)
for name in ['a', 'b', 'c']:
print(f"{name.upper():<12} {results[name]['structure']:<35} {results[name]['hardness']:<20}")
# TTT図の簡易プロット(概念図)
fig, ax = plt.subplots(figsize=(12, 8))
# 時間軸(対数)
time = np.logspace(-1, 4, 200)
# パーライト変態曲線(簡易C字型)
P_start = 550 + 150 * (np.log10(time / pearlite_nose['time']))**2
P_start = np.clip(P_start, 400, 727)
# ベイナイト変態曲線
B_start = 350 + 80 * (np.log10(time / bainite_nose['time']))**2
B_start = np.clip(B_start, 250, 500)
ax.semilogx(time, P_start, 'r-', linewidth=2, label='Pearlite Start')
ax.semilogx(time, B_start, 'b-', linewidth=2, label='Bainite Start')
ax.axhline(y=Ms_temp, color='green', linestyle='-', linewidth=2.5, label=f'Ms = {Ms_temp}°C')
# シナリオの冷却曲線をプロット
# Scenario A
cool_time_a = scenarios['a']['cool_time']
hold_time_a = scenarios['a']['hold_time']
time_a = [0, cool_time_a, cool_time_a + hold_time_a]
temp_a = [850, 550, 550]
ax.plot(time_a, temp_a, 'ko-', linewidth=2.5, markersize=8, label='Scenario A', alpha=0.7)
# Scenario B
time_b = [0, scenarios['b']['cool_time']]
temp_b = [850, 200]
ax.plot(time_b, temp_b, 'mo-', linewidth=2.5, markersize=8, label='Scenario B', alpha=0.7)
# Scenario C
cool_time_c = scenarios['c']['cool_time']
hold_time_c = scenarios['c']['hold_time']
time_c = [0, cool_time_c, cool_time_c + hold_time_c]
temp_c = [850, 350, 350]
ax.plot(time_c, temp_c, 'co-', linewidth=2.5, markersize=8, label='Scenario C', alpha=0.7)
ax.set_xlabel('Time [s]', fontsize=13)
ax.set_ylabel('Temperature [°C]', fontsize=13)
ax.set_title('TTT Diagram and Cooling Paths for Eutectoid Steel', fontsize=15, fontweight='bold')
ax.legend(fontsize=11, loc='upper right')
ax.grid(True, alpha=0.3, which='both')
ax.set_xlim(0.1, 1e4)
ax.set_ylim(0, 900)
plt.tight_layout()
plt.savefig('ttt_scenarios.png', dpi=300, bbox_inches='tight')
plt.show()
# 推奨用途
print("\n=== Recommended Applications ===")
print("Scenario A (Pearlite): Rails, wire ropes (high ductility, wear resistance)")
print("Scenario B (Martensite): Cutting tools, bearings (maximum hardness)")
print("Scenario C (Bainite): Gears, springs (balanced hardness and toughness)")
期待される出力:
Scenario A: 100% Pearlite (~20-25 HRC) Scenario B: ~100% Martensite (~63-65 HRC) Scenario C: 100% Bainite (~40-50 HRC)
解説: (a)はパーライトノーズ温度で保持するため、完全にパーライト変態します。(b)はMs温度以下まで急冷するため、マルテンサイト組織が得られます。(c)はベイナイトノーズ温度で長時間保持するため、ベイナイト変態が進行します。TTT図上で冷却曲線がどの変態曲線と交わるかを確認することで、組織予測が可能です。
確認方法: 上記の演習問題(Exercise 1-6)をすべて自力で解けることを確認してください。特に、Exercise 5(時効硬化の最適化)とExercise 6(TTT図による組織予測)は、実用的な問題解決能力を評価する重要な課題です。