Chapter 1: 金属結合と結晶構造

金属の自由電子モデル、FCC/BCC/HCP結晶構造、ブラベー格子、ミラー指数

1.1 金属結合の電子論

金属の特性を理解するには、金属結合の本質を知ることが重要です。金属結合は、イオン化した金属原子(陽イオン)が、自由に動き回る電子(自由電子)によって結びついている状態です。この自由電子モデルによって、金属の電気伝導性、熱伝導性、光沢などの特性を説明できます。

1.1.1 Drudeモデル

Drudeモデルは、金属中の自由電子を古典的な気体分子として扱うモデルです。このモデルでは、電子は金属イオンの間を自由に動き回り、イオンや他の電子と衝突することで散乱されます。

電気伝導度の式:

$$\sigma = \frac{ne^2\tau}{m}$$

ここで、$n$は電子密度、$e$は電子の電荷、$\tau$は緩和時間、$m$は電子の質量です。

この式から、電気伝導度は電子密度と緩和時間に比例することがわかります。金属の電気抵抗は温度上昇とともに増加しますが、これは格子振動(フォノン)による電子の散乱が増えるためです。

1.1.2 フェルミ-ディラック分布

量子力学的には、電子はフェルミ粒子であり、パウリの排他原理に従います。温度$T$におけるエネルギー$E$の状態の占有確率は、フェルミ-ディラック分布関数で表されます:

$$f(E) = \frac{1}{1 + \exp\left(\frac{E - E_F}{k_BT}\right)}$$

ここで、$E_F$はフェルミエネルギー、$k_B$はボルツマン定数です。

絶対零度($T = 0$ K)では、フェルミエネルギー以下のすべての状態が占有され、それより上の状態は空になります。室温でも、金属のフェルミエネルギー(数eV)は熱エネルギー$k_BT$(約0.025 eV)よりはるかに大きいため、フェルミ-ディラック分布はステップ関数に近い形をしています。

1.1.3 状態密度

金属中の電子の状態密度$D(E)$は、単位エネルギー当たりの状態数を表します。自由電子モデルでは、3次元の状態密度は次のように表されます:

$$D(E) = \frac{2\pi V}{h^3}(2m)^{3/2}E^{1/2}$$

ここで、$V$は体積、$h$はプランク定数、$m$は電子の質量です。

コード例1: Drudeモデルによる電気伝導度計算

import numpy as np
import matplotlib.pyplot as plt

# 物理定数
e = 1.602e-19  # 電子の電荷 (C)
m_e = 9.109e-31  # 電子の質量 (kg)

def calculate_conductivity(n, tau):
    """
    Drudeモデルで電気伝導度を計算

    Parameters:
    -----------
    n : float
        電子密度 (m^-3)
    tau : float
        緩和時間 (s)

    Returns:
    --------
    sigma : float
        電気伝導度 (S/m)
    """
    sigma = (n * e**2 * tau) / m_e
    return sigma

# 代表的な金属の電子密度 (m^-3)
metals = {
    'Cu': 8.45e28,   # 銅
    'Ag': 5.85e28,   # 銀
    'Al': 18.1e28,   # アルミニウム
    'Fe': 17.0e28,   # 鉄
    'Au': 5.90e28    # 金
}

# 緩和時間(典型的な値)
tau = 2.5e-14  # s

# 各金属の電気伝導度を計算
print("金属の電気伝導度 (Drudeモデル):")
print("-" * 50)
for metal, n in metals.items():
    sigma = calculate_conductivity(n, tau)
    resistivity = 1 / sigma
    print(f"{metal:4s}: σ = {sigma:.2e} S/m, ρ = {resistivity*1e8:.2f} μΩ·cm")

# 温度依存性のシミュレーション(銅)
temperatures = np.linspace(100, 500, 100)  # K
# 緩和時間は温度に反比例すると仮定
tau_T = tau * 300 / temperatures  # 300Kで規格化

conductivity_T = np.array([calculate_conductivity(metals['Cu'], t) for t in tau_T])
resistivity_T = 1 / conductivity_T

# グラフ描画
plt.figure(figsize=(10, 6))
plt.plot(temperatures, resistivity_T * 1e8, 'b-', linewidth=2)
plt.xlabel('温度 (K)', fontsize=12)
plt.ylabel('電気抵抗率 (μΩ·cm)', fontsize=12)
plt.title('銅の電気抵抗率の温度依存性 (Drudeモデル)', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('cu_resistivity_vs_temperature.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n✓ グラフを 'cu_resistivity_vs_temperature.png' として保存しました")

コード例2: フェルミエネルギーと状態密度の計算

import numpy as np
import matplotlib.pyplot as plt
from scipy import constants

# 物理定数
h = constants.h  # プランク定数
hbar = constants.hbar  # ディラック定数
m_e = constants.m_e  # 電子の質量
k_B = constants.k  # ボルツマン定数
e = constants.e  # 電子の電荷

def fermi_energy(n):
    """
    フェルミエネルギーを計算

    Parameters:
    -----------
    n : float
        電子密度 (m^-3)

    Returns:
    --------
    E_F : float
        フェルミエネルギー (J)
    """
    E_F = (hbar**2 / (2 * m_e)) * (3 * np.pi**2 * n)**(2/3)
    return E_F

def fermi_dirac(E, E_F, T):
    """
    フェルミ-ディラック分布関数

    Parameters:
    -----------
    E : array-like
        エネルギー (J)
    E_F : float
        フェルミエネルギー (J)
    T : float
        温度 (K)

    Returns:
    --------
    f : array-like
        占有確率
    """
    if T == 0:
        return np.where(E <= E_F, 1.0, 0.0)
    else:
        return 1 / (1 + np.exp((E - E_F) / (k_B * T)))

def density_of_states(E):
    """
    自由電子の状態密度(3次元)

    Parameters:
    -----------
    E : array-like
        エネルギー (J)

    Returns:
    --------
    D : array-like
        状態密度 (J^-1 m^-3)
    """
    # 単位体積あたり
    D = (1 / (2 * np.pi**2)) * (2 * m_e / hbar**2)**(3/2) * np.sqrt(E)
    return D

# 銅のパラメータ
n_Cu = 8.45e28  # 電子密度 (m^-3)
E_F_Cu = fermi_energy(n_Cu)
E_F_eV = E_F_Cu / e  # eV単位

print(f"銅のフェルミエネルギー: {E_F_eV:.2f} eV")
print(f"フェルミ速度: {np.sqrt(2 * E_F_Cu / m_e) / 1e6:.2f} × 10^6 m/s")

# フェルミ-ディラック分布のプロット
E_range = np.linspace(0, 2 * E_F_Cu, 1000)
E_range_eV = E_range / e

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 左図: フェルミ-ディラック分布
temperatures = [0, 300, 1000, 3000]
for T in temperatures:
    f = fermi_dirac(E_range, E_F_Cu, T)
    label = f'{T} K' if T > 0 else '0 K'
    axes[0].plot(E_range_eV, f, linewidth=2, label=label)

axes[0].axvline(E_F_eV, color='red', linestyle='--', linewidth=1.5, label=f'$E_F$ = {E_F_eV:.2f} eV')
axes[0].set_xlabel('エネルギー (eV)', fontsize=12)
axes[0].set_ylabel('占有確率 f(E)', fontsize=12)
axes[0].set_title('フェルミ-ディラック分布', fontsize=14, fontweight='bold')
axes[0].legend(fontsize=10)
axes[0].grid(True, alpha=0.3)
axes[0].set_xlim(0, 2 * E_F_eV)
axes[0].set_ylim(-0.05, 1.05)

# 右図: 状態密度
D = density_of_states(E_range[E_range > 0])
E_positive_eV = E_range_eV[E_range > 0]

axes[1].plot(E_positive_eV, D / 1e47, 'b-', linewidth=2)
axes[1].axvline(E_F_eV, color='red', linestyle='--', linewidth=1.5, label=f'$E_F$ = {E_F_eV:.2f} eV')
axes[1].set_xlabel('エネルギー (eV)', fontsize=12)
axes[1].set_ylabel('状態密度 (10^47 states/(J·m³))', fontsize=12)
axes[1].set_title('自由電子の状態密度', fontsize=14, fontweight='bold')
axes[1].legend(fontsize=10)
axes[1].grid(True, alpha=0.3)
axes[1].set_xlim(0, 2 * E_F_eV)

plt.tight_layout()
plt.savefig('fermi_dirac_and_dos.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n✓ グラフを 'fermi_dirac_and_dos.png' として保存しました")

1.2 結晶構造の基礎

金属の多くは結晶構造を持ち、原子が規則正しく配列しています。金属の機械的性質、電気的性質、熱的性質は、この結晶構造に大きく依存します。代表的な金属結晶構造として、面心立方格子(FCC)、体心立方格子(BCC)、六方最密充填構造(HCP)があります。

1.2.1 面心立方格子(FCC: Face-Centered Cubic)

FCC構造は、立方体の各頂点と各面の中心に原子が配置された構造です。代表的なFCC金属には、銅(Cu)、アルミニウム(Al)、金(Au)、銀(Ag)、ニッケル(Ni)などがあります。

flowchart TD A[FCC構造] --> B[最密充填構造] B --> C[充填率 74%] B --> D[配位数 12] A --> E[すべり系が多い] E --> F[延性が高い] F --> G[加工しやすい] A --> H[代表的な金属] H --> I[Cu, Al, Au, Ag, Ni]

1.2.2 体心立方格子(BCC: Body-Centered Cubic)

BCC構造は、立方体の各頂点と中心に原子が配置された構造です。代表的なBCC金属には、鉄(Fe、常温)、クロム(Cr)、タングステン(W)、モリブデン(Mo)などがあります。

  • 格子定数: 立方体の一辺の長さ $a$
  • 原子数: 単位格子あたり 2 個(頂点 $8 \times 1/8 = 1$、体心 $1$)
  • 配位数: 8
  • 原子半径: $r = \frac{\sqrt{3}a}{4}$
  • 充填率: $\frac{\sqrt{3}\pi}{8} \approx 0.68$ (68%)

1.2.3 六方最密充填構造(HCP: Hexagonal Close-Packed)

HCP構造は、六方晶系の最密充填構造です。代表的なHCP金属には、マグネシウム(Mg)、チタン(Ti)、亜鉛(Zn)、コバルト(Co)などがあります。

  • 格子定数: 底面の辺の長さ $a$、高さ $c$
  • 原子数: 単位格子あたり 6 個
  • 配位数: 12
  • 理想的な軸比: $c/a = \sqrt{8/3} \approx 1.633$
  • 充填率: $\frac{\pi}{3\sqrt{2}} \approx 0.74$ (74%、FCCと同じ)

コード例3: 結晶構造の3D可視化(FCC/BCC/HCP)

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def create_fcc_structure(a=1.0):
    """
    FCC構造の原子座標を生成

    Parameters:
    -----------
    a : float
        格子定数

    Returns:
    --------
    positions : ndarray
        原子座標 (N, 3)
    """
    positions = []

    # 頂点の原子(単位格子内の原子のみ)
    corners = [
        [0, 0, 0], [a, 0, 0], [0, a, 0], [0, 0, a],
        [a, a, 0], [a, 0, a], [0, a, a], [a, a, a]
    ]

    # 面心の原子
    face_centers = [
        [a/2, a/2, 0], [a/2, 0, a/2], [0, a/2, a/2],
        [a/2, a/2, a], [a/2, a, a/2], [a, a/2, a/2]
    ]

    positions.extend(corners)
    positions.extend(face_centers)

    return np.array(positions)

def create_bcc_structure(a=1.0):
    """
    BCC構造の原子座標を生成

    Parameters:
    -----------
    a : float
        格子定数

    Returns:
    --------
    positions : ndarray
        原子座標 (N, 3)
    """
    positions = []

    # 頂点の原子
    corners = [
        [0, 0, 0], [a, 0, 0], [0, a, 0], [0, 0, a],
        [a, a, 0], [a, 0, a], [0, a, a], [a, a, a]
    ]

    # 体心の原子
    body_center = [[a/2, a/2, a/2]]

    positions.extend(corners)
    positions.extend(body_center)

    return np.array(positions)

def create_hcp_structure(a=1.0, c_over_a=1.633):
    """
    HCP構造の原子座標を生成(簡易版)

    Parameters:
    -----------
    a : float
        格子定数(底面)
    c_over_a : float
        軸比 c/a

    Returns:
    --------
    positions : ndarray
        原子座標 (N, 3)
    """
    c = a * c_over_a
    positions = []

    # 底面の原子(A層)
    positions.append([0, 0, 0])
    positions.append([a, 0, 0])
    positions.append([a/2, a*np.sqrt(3)/2, 0])

    # 中間層の原子(B層)
    positions.append([a/2, a*np.sqrt(3)/6, c/2])

    # 上面の原子(A層)
    positions.append([0, 0, c])
    positions.append([a, 0, c])
    positions.append([a/2, a*np.sqrt(3)/2, c])

    return np.array(positions)

def plot_crystal_structure(positions, title, ax, color='blue', atom_size=300):
    """
    結晶構造を3Dプロット
    """
    ax.scatter(positions[:, 0], positions[:, 1], positions[:, 2],
               c=color, s=atom_size, alpha=0.7, edgecolors='black', linewidth=1.5)

    ax.set_xlabel('X', fontsize=10, fontweight='bold')
    ax.set_ylabel('Y', fontsize=10, fontweight='bold')
    ax.set_zlabel('Z', fontsize=10, fontweight='bold')
    ax.set_title(title, fontsize=12, fontweight='bold', pad=10)

    # 軸の範囲を設定
    max_coord = np.max(positions)
    ax.set_xlim([-0.2, max_coord + 0.2])
    ax.set_ylim([-0.2, max_coord + 0.2])
    ax.set_zlim([-0.2, max_coord + 0.2])

    ax.set_box_aspect([1, 1, 1])

# 3つの結晶構造を生成
a = 1.0
fcc_pos = create_fcc_structure(a)
bcc_pos = create_bcc_structure(a)
hcp_pos = create_hcp_structure(a)

# プロット
fig = plt.figure(figsize=(16, 5))

ax1 = fig.add_subplot(131, projection='3d')
plot_crystal_structure(fcc_pos, 'FCC構造\n(Cu, Al, Au, Ag)', ax1, color='#FF6B6B')

ax2 = fig.add_subplot(132, projection='3d')
plot_crystal_structure(bcc_pos, 'BCC構造\n(Fe, Cr, W, Mo)', ax2, color='#4ECDC4')

ax3 = fig.add_subplot(133, projection='3d')
plot_crystal_structure(hcp_pos, 'HCP構造\n(Mg, Ti, Zn, Co)', ax3, color='#95E1D3')

plt.tight_layout()
plt.savefig('crystal_structures_3d.png', dpi=300, bbox_inches='tight')
plt.show()

# 充填率と配位数の計算
print("結晶構造の比較:")
print("=" * 60)
print(f"{'構造':<8} {'充填率':<15} {'配位数':<10} {'代表的な金属'}")
print("-" * 60)
print(f"{'FCC':<8} {np.pi/(3*np.sqrt(2)):.4f} (74%)    {12:<10} Cu, Al, Au, Ag, Ni")
print(f"{'BCC':<8} {np.sqrt(3)*np.pi/8:.4f} (68%)    {8:<10} Fe, Cr, W, Mo")
print(f"{'HCP':<8} {np.pi/(3*np.sqrt(2)):.4f} (74%)    {12:<10} Mg, Ti, Zn, Co")
print("=" * 60)

print("\n✓ グラフを 'crystal_structures_3d.png' として保存しました")

コード例4: 充填率と配位数の詳細計算

import numpy as np
import matplotlib.pyplot as plt

def calculate_fcc_properties(a):
    """FCC構造の物性を計算"""
    # 原子半径
    r = a / (2 * np.sqrt(2))

    # 原子数(単位格子あたり)
    n_atoms = 4

    # 単位格子の体積
    V_cell = a**3

    # 原子の体積
    V_atom = (4/3) * np.pi * r**3

    # 充填率
    packing_fraction = (n_atoms * V_atom) / V_cell

    # 配位数
    coordination_number = 12

    # 最近接原子間距離
    nearest_neighbor = 2 * r

    return {
        'structure': 'FCC',
        'lattice_constant': a,
        'atomic_radius': r,
        'atoms_per_cell': n_atoms,
        'packing_fraction': packing_fraction,
        'coordination_number': coordination_number,
        'nearest_neighbor': nearest_neighbor
    }

def calculate_bcc_properties(a):
    """BCC構造の物性を計算"""
    # 原子半径
    r = (np.sqrt(3) * a) / 4

    # 原子数
    n_atoms = 2

    # 単位格子の体積
    V_cell = a**3

    # 原子の体積
    V_atom = (4/3) * np.pi * r**3

    # 充填率
    packing_fraction = (n_atoms * V_atom) / V_cell

    # 配位数
    coordination_number = 8

    # 最近接原子間距離
    nearest_neighbor = 2 * r

    return {
        'structure': 'BCC',
        'lattice_constant': a,
        'atomic_radius': r,
        'atoms_per_cell': n_atoms,
        'packing_fraction': packing_fraction,
        'coordination_number': coordination_number,
        'nearest_neighbor': nearest_neighbor
    }

def calculate_hcp_properties(a, c_over_a=1.633):
    """HCP構造の物性を計算"""
    c = a * c_over_a

    # 原子半径(最近接原子間距離の半分)
    r = a / 2

    # 原子数
    n_atoms = 6

    # 単位格子の体積(六角柱)
    V_cell = (3 * np.sqrt(3) / 2) * a**2 * c

    # 原子の体積
    V_atom = (4/3) * np.pi * r**3

    # 充填率
    packing_fraction = (n_atoms * V_atom) / V_cell

    # 配位数
    coordination_number = 12

    # 最近接原子間距離
    nearest_neighbor = 2 * r

    return {
        'structure': 'HCP',
        'lattice_constant_a': a,
        'lattice_constant_c': c,
        'c_over_a': c_over_a,
        'atomic_radius': r,
        'atoms_per_cell': n_atoms,
        'packing_fraction': packing_fraction,
        'coordination_number': coordination_number,
        'nearest_neighbor': nearest_neighbor
    }

# 格子定数(任意の単位)
a = 1.0

# 各構造の物性を計算
fcc_props = calculate_fcc_properties(a)
bcc_props = calculate_bcc_properties(a)
hcp_props = calculate_hcp_properties(a)

# 結果を表示
print("\n結晶構造の詳細物性比較")
print("=" * 80)

for props in [fcc_props, bcc_props, hcp_props]:
    print(f"\n【{props['structure']}構造】")
    print("-" * 80)
    if props['structure'] == 'HCP':
        print(f"  格子定数 a:           {props['lattice_constant_a']:.4f}")
        print(f"  格子定数 c:           {props['lattice_constant_c']:.4f}")
        print(f"  軸比 c/a:             {props['c_over_a']:.4f}")
    else:
        print(f"  格子定数:             {props['lattice_constant']:.4f}")
    print(f"  原子半径:             {props['atomic_radius']:.4f}")
    print(f"  単位格子あたり原子数: {props['atoms_per_cell']}")
    print(f"  充填率:               {props['packing_fraction']:.4f} ({props['packing_fraction']*100:.1f}%)")
    print(f"  配位数:               {props['coordination_number']}")
    print(f"  最近接原子間距離:     {props['nearest_neighbor']:.4f}")

# 視覚化
structures = ['FCC', 'BCC', 'HCP']
packing_fractions = [fcc_props['packing_fraction'],
                     bcc_props['packing_fraction'],
                     hcp_props['packing_fraction']]
coordination_numbers = [fcc_props['coordination_number'],
                        bcc_props['coordination_number'],
                        hcp_props['coordination_number']]

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

# 充填率の比較
colors = ['#FF6B6B', '#4ECDC4', '#95E1D3']
bars1 = ax1.bar(structures, [pf * 100 for pf in packing_fractions], color=colors, alpha=0.8, edgecolor='black', linewidth=2)
ax1.set_ylabel('充填率 (%)', fontsize=12, fontweight='bold')
ax1.set_title('結晶構造の充填率比較', fontsize=14, fontweight='bold')
ax1.set_ylim(0, 80)
ax1.grid(axis='y', alpha=0.3)

# バーに数値を表示
for bar in bars1:
    height = bar.get_height()
    ax1.text(bar.get_x() + bar.get_width()/2., height + 1,
             f'{height:.1f}%', ha='center', va='bottom', fontsize=11, fontweight='bold')

# 配位数の比較
bars2 = ax2.bar(structures, coordination_numbers, color=colors, alpha=0.8, edgecolor='black', linewidth=2)
ax2.set_ylabel('配位数', fontsize=12, fontweight='bold')
ax2.set_title('結晶構造の配位数比較', fontsize=14, fontweight='bold')
ax2.set_ylim(0, 14)
ax2.grid(axis='y', alpha=0.3)

# バーに数値を表示
for bar in bars2:
    height = bar.get_height()
    ax2.text(bar.get_x() + bar.get_width()/2., height + 0.3,
             f'{int(height)}', ha='center', va='bottom', fontsize=11, fontweight='bold')

plt.tight_layout()
plt.savefig('crystal_properties_comparison.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n" + "=" * 80)
print("✓ グラフを 'crystal_properties_comparison.png' として保存しました")

1.3 ミラー指数

結晶中の面や方位を表記するために、ミラー指数が用いられます。ミラー指数は、結晶構造の対称性を理解し、X線回折データを解析する上で不可欠です。

1.3.1 結晶面の表記 (hkl)

結晶面は、3つの整数 $(h, k, l)$ で表されます。これらは、その面が結晶軸 $a, b, c$ を切る点の逆数の比を最小の整数で表したものです。

ミラー指数の求め方:

  1. 面が各結晶軸を切る点の座標を求める(例:$x=2, y=3, z=6$)
  2. その逆数を取る(例:$1/2, 1/3, 1/6$)
  3. 最小公倍数を掛けて整数にする(例:$\times 6$ で $3, 2, 1$)
  4. $(hkl) = (321)$ と表記

代表的な面:

1.3.2 結晶方位の表記 [uvw]

結晶方位(方向)は、角括弧 $[uvw]$ で表されます。これは、原点から $(u, v, w)$ の点へ向かうベクトルの方向を示します。

1.3.3 面間隔の計算

立方晶系において、$(hkl)$ 面の面間隔 $d_{hkl}$ は次の式で計算されます:

$$d_{hkl} = \frac{a}{\sqrt{h^2 + k^2 + l^2}}$$

ここで、$a$ は格子定数です。

コード例5: ミラー指数と面間隔の計算

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

def calculate_d_spacing(a, h, k, l, crystal_system='cubic'):
    """
    面間隔を計算

    Parameters:
    -----------
    a : float
        格子定数
    h, k, l : int
        ミラー指数
    crystal_system : str
        結晶系('cubic', 'tetragonal', 'hexagonal'など)

    Returns:
    --------
    d : float
        面間隔
    """
    if crystal_system == 'cubic':
        d = a / np.sqrt(h**2 + k**2 + l**2)
    else:
        raise NotImplementedError(f"{crystal_system}系は未実装です")

    return d

def plot_plane(h, k, l, a=1.0, ax=None):
    """
    (hkl)面を可視化

    Parameters:
    -----------
    h, k, l : int
        ミラー指数
    a : float
        格子定数
    ax : matplotlib axis
        プロット用の軸
    """
    if ax is None:
        fig = plt.figure(figsize=(8, 8))
        ax = fig.add_subplot(111, projection='3d')

    # 面が軸を切る点を計算
    # h, k, l がゼロの場合は無限遠(実際には大きな値)
    intercepts = []
    for index in [h, k, l]:
        if index != 0:
            intercepts.append(a / index)
        else:
            intercepts.append(10 * a)  # 大きな値

    # 面を描画(三角形として近似)
    points = [
        [intercepts[0], 0, 0],
        [0, intercepts[1], 0],
        [0, 0, intercepts[2]]
    ]

    # 面の多角形
    poly = [[points[0], points[1], points[2]]]
    ax.add_collection3d(Poly3DCollection(poly, alpha=0.5, facecolor='cyan', edgecolor='blue', linewidth=2))

    # 座標軸を描画
    ax.plot([0, a], [0, 0], [0, 0], 'r-', linewidth=2, label='a軸')
    ax.plot([0, 0], [0, a], [0, 0], 'g-', linewidth=2, label='b軸')
    ax.plot([0, 0], [0, 0], [0, a], 'b-', linewidth=2, label='c軸')

    # 切片にマーカー
    if h != 0:
        ax.scatter([intercepts[0]], [0], [0], c='red', s=100, marker='o')
    if k != 0:
        ax.scatter([0], [intercepts[1]], [0], c='green', s=100, marker='o')
    if l != 0:
        ax.scatter([0], [0], [intercepts[2]], c='blue', s=100, marker='o')

    ax.set_xlabel('X (a軸)', fontsize=11, fontweight='bold')
    ax.set_ylabel('Y (b軸)', fontsize=11, fontweight='bold')
    ax.set_zlabel('Z (c軸)', fontsize=11, fontweight='bold')
    ax.set_title(f'({h}{k}{l}) 面', fontsize=13, fontweight='bold')

    max_val = max(intercepts) * 0.6
    ax.set_xlim([0, max_val])
    ax.set_ylim([0, max_val])
    ax.set_zlim([0, max_val])

    ax.legend(fontsize=9)

    return ax

# 代表的な面の可視化
fig = plt.figure(figsize=(16, 5))

planes = [(1, 0, 0), (1, 1, 0), (1, 1, 1)]
a = 1.0

for i, (h, k, l) in enumerate(planes):
    ax = fig.add_subplot(1, 3, i+1, projection='3d')
    plot_plane(h, k, l, a, ax)

    # 面間隔を計算して表示
    d = calculate_d_spacing(a, h, k, l)
    ax.text2D(0.05, 0.95, f'd = {d:.3f}a', transform=ax.transAxes, fontsize=11,
              verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))

plt.tight_layout()
plt.savefig('miller_indices_planes.png', dpi=300, bbox_inches='tight')
plt.show()

# 主要な面の面間隔を計算
print("\n立方晶系における主要な面の面間隔")
print("=" * 60)
print(f"{'面':<10} {'面間隔 (単位: a)':<20} {'相対強度'}")
print("-" * 60)

important_planes = [
    (1, 0, 0), (1, 1, 0), (1, 1, 1),
    (2, 0, 0), (2, 1, 0), (2, 1, 1),
    (2, 2, 0), (3, 1, 0), (2, 2, 2)
]

for h, k, l in important_planes:
    d = calculate_d_spacing(a, h, k, l)
    # 構造因子による相対強度(簡易版、FCC を仮定)
    if (h % 2 == 0 and k % 2 == 0 and l % 2 == 0) or \
       (h % 2 == 1 and k % 2 == 1 and l % 2 == 1):
        intensity = "強"
    else:
        intensity = "消滅 (FCC)"

    print(f"({h}{k}{l}){'':<7} {d:.4f} a{'':<15} {intensity}")

print("=" * 60)
print("\n注:FCC構造では、すべて偶数またはすべて奇数の(hkl)面のみが回折を示します")
print("✓ グラフを 'miller_indices_planes.png' として保存しました")

1.4 Python実践:ASE/pymatgenによる結晶構造の生成と解析

実際の材料科学研究では、pymatgenASE(Atomic Simulation Environment)といったPythonライブラリを用いて結晶構造を生成・操作します。これらのツールは、密度汎関数理論(DFT)計算との連携や、Materials Project データベースへのアクセスも可能です。

コード例6: ASEによる結晶構造生成と可視化

"""
ASE (Atomic Simulation Environment) を使用した結晶構造の生成と解析

注: ASEのインストールが必要です: pip install ase
"""

try:
    from ase import Atoms
    from ase.build import bulk
    from ase.visualize import view
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    import numpy as np

    # 各種金属の結晶構造を生成
    structures = {}

    # 銅(FCC)
    cu = bulk('Cu', 'fcc', a=3.615)  # a = 3.615 Å
    structures['Cu (FCC)'] = cu

    # 鉄(BCC)
    fe = bulk('Fe', 'bcc', a=2.866)  # a = 2.866 Å
    structures['Fe (BCC)'] = fe

    # マグネシウム(HCP)
    mg = bulk('Mg', 'hcp', a=3.209, c=5.211)  # a = 3.209 Å, c = 5.211 Å
    structures['Mg (HCP)'] = mg

    # アルミニウム(FCC)
    al = bulk('Al', 'fcc', a=4.046)  # a = 4.046 Å
    structures['Al (FCC)'] = al

    # 各構造の情報を表示
    print("ASEによる金属結晶構造の生成")
    print("=" * 80)

    for name, atoms in structures.items():
        print(f"\n【{name}】")
        print("-" * 80)
        print(f"  化学式:         {atoms.get_chemical_formula()}")
        print(f"  原子数:         {len(atoms)}")
        print(f"  格子定数 (Å):   a = {atoms.cell.cellpar()[0]:.3f}, "
              f"b = {atoms.cell.cellpar()[1]:.3f}, c = {atoms.cell.cellpar()[2]:.3f}")
        print(f"  セル角度 (deg): α = {atoms.cell.cellpar()[3]:.1f}, "
              f"β = {atoms.cell.cellpar()[4]:.1f}, γ = {atoms.cell.cellpar()[5]:.1f}")
        print(f"  体積 (Ų):      {atoms.get_volume():.3f}")
        print(f"  密度 (g/cm³):   計算値 = {atoms.get_masses().sum() / atoms.get_volume() * 1.66054:.3f}")

    # スーパーセルの作成(Cu の 2x2x2)
    cu_supercell = cu.repeat((2, 2, 2))
    print(f"\n\n【Cu スーパーセル (2×2×2)】")
    print("-" * 80)
    print(f"  原子数:         {len(cu_supercell)}")
    print(f"  体積 (Ų):      {cu_supercell.get_volume():.3f}")

    # 3D可視化用の関数
    def plot_ase_structure(atoms, title, ax):
        """ASE Atomsオブジェクトを3Dプロット"""
        positions = atoms.get_positions()

        ax.scatter(positions[:, 0], positions[:, 1], positions[:, 2],
                   c='#FF6B6B', s=300, alpha=0.7, edgecolors='black', linewidth=1.5)

        # セルの境界を描画
        cell = atoms.cell

        # セルの頂点
        origin = np.array([0, 0, 0])
        vertices = [
            origin,
            cell[0],
            cell[1],
            cell[2],
            cell[0] + cell[1],
            cell[0] + cell[2],
            cell[1] + cell[2],
            cell[0] + cell[1] + cell[2]
        ]

        # セルのエッジ
        edges = [
            (0, 1), (0, 2), (0, 3),
            (1, 4), (1, 5), (2, 4),
            (2, 6), (3, 5), (3, 6),
            (4, 7), (5, 7), (6, 7)
        ]

        for i, j in edges:
            edge = np.array([vertices[i], vertices[j]])
            ax.plot3D(edge[:, 0], edge[:, 1], edge[:, 2], 'k-', linewidth=1, alpha=0.6)

        ax.set_xlabel('X (Å)', fontsize=10, fontweight='bold')
        ax.set_ylabel('Y (Å)', fontsize=10, fontweight='bold')
        ax.set_zlabel('Z (Å)', fontsize=10, fontweight='bold')
        ax.set_title(title, fontsize=12, fontweight='bold', pad=10)
        ax.set_box_aspect([1, 1, 1])

    # プロット
    fig = plt.figure(figsize=(16, 5))

    plot_structures = [(cu, 'Cu (FCC)'), (fe, 'Fe (BCC)'), (mg, 'Mg (HCP)')]

    for i, (atoms, name) in enumerate(plot_structures):
        ax = fig.add_subplot(1, 3, i+1, projection='3d')
        plot_ase_structure(atoms, name, ax)

    plt.tight_layout()
    plt.savefig('ase_crystal_structures.png', dpi=300, bbox_inches='tight')
    plt.show()

    print("\n" + "=" * 80)
    print("✓ グラフを 'ase_crystal_structures.png' として保存しました")
    print("\n※ ASEでは atoms.edit() または from ase.visualize import view; view(atoms) で")
    print("  インタラクティブな3D可視化が可能です(GUI環境が必要)")

except ImportError:
    print("エラー: ASEがインストールされていません")
    print("インストール方法: pip install ase")
    print("\n代替として、以下のように手動で結晶構造を定義できます:")
    print("""
import numpy as np

# FCC構造の手動定義
a = 3.615  # 銅の格子定数 (Å)
fcc_positions = np.array([
    [0.0, 0.0, 0.0],
    [0.5*a, 0.5*a, 0.0],
    [0.5*a, 0.0, 0.5*a],
    [0.0, 0.5*a, 0.5*a]
])
print("FCC原子座標 (Å):")
print(fcc_positions)
""")

コード例7: pymatgenによる結晶構造の高度な解析

"""
pymatgen を使用した結晶構造の高度な解析

注: pymatgenのインストールが必要です: pip install pymatgen
"""

try:
    from pymatgen.core import Structure, Lattice
    from pymatgen.analysis.structure_analyzer import SpacegroupAnalyzer
    from pymatgen.symmetry.analyzer import SpacegroupAnalyzer as SGA
    import numpy as np

    # 銅(FCC)の構造を生成
    lattice_cu = Lattice.cubic(3.615)  # a = 3.615 Å
    species_cu = ['Cu'] * 4
    coords_cu = [
        [0.0, 0.0, 0.0],
        [0.5, 0.5, 0.0],
        [0.5, 0.0, 0.5],
        [0.0, 0.5, 0.5]
    ]
    cu_structure = Structure(lattice_cu, species_cu, coords_cu)

    # 鉄(BCC)の構造を生成
    lattice_fe = Lattice.cubic(2.866)  # a = 2.866 Å
    species_fe = ['Fe'] * 2
    coords_fe = [
        [0.0, 0.0, 0.0],
        [0.5, 0.5, 0.5]
    ]
    fe_structure = Structure(lattice_fe, species_fe, coords_fe)

    # マグネシウム(HCP)の構造を生成
    a_mg = 3.209
    c_mg = 5.211
    lattice_mg = Lattice.hexagonal(a_mg, c_mg)
    species_mg = ['Mg'] * 2
    coords_mg = [
        [1/3, 2/3, 1/4],
        [2/3, 1/3, 3/4]
    ]
    mg_structure = Structure(lattice_mg, species_mg, coords_mg)

    structures = {
        'Cu (FCC)': cu_structure,
        'Fe (BCC)': fe_structure,
        'Mg (HCP)': mg_structure
    }

    print("pymatgenによる結晶構造の詳細解析")
    print("=" * 80)

    for name, structure in structures.items():
        print(f"\n【{name}】")
        print("-" * 80)

        # 基本情報
        print(f"  化学式:           {structure.composition.reduced_formula}")
        print(f"  空間群:           ", end="")

        try:
            sga = SpacegroupAnalyzer(structure)
            spacegroup = sga.get_space_group_symbol()
            spacegroup_number = sga.get_space_group_number()
            print(f"{spacegroup} (No. {spacegroup_number})")

            # 対称操作の数
            print(f"  対称操作の数:     {len(sga.get_symmetry_operations())}")

            # 点群
            print(f"  点群:             {sga.get_point_group_symbol()}")

        except Exception as e:
            print(f"解析エラー: {e}")

        # 格子情報
        abc = structure.lattice.abc
        angles = structure.lattice.angles
        print(f"  格子定数 (Å):     a = {abc[0]:.3f}, b = {abc[1]:.3f}, c = {abc[2]:.3f}")
        print(f"  格子角度 (deg):   α = {angles[0]:.1f}, β = {angles[1]:.1f}, γ = {angles[2]:.1f}")
        print(f"  体積 (Ų):        {structure.volume:.3f}")
        print(f"  密度 (g/cm³):     {structure.density:.3f}")

        # 最近接原子間距離
        print(f"\n  最近接原子間距離:")
        all_nn_distances = []
        for i, site in enumerate(structure):
            neighbors = structure.get_neighbors(site, 4.0)  # 4 Å以内
            if neighbors:
                nn_dist = min([neighbor[1] for neighbor in neighbors])
                all_nn_distances.append(nn_dist)

        if all_nn_distances:
            avg_nn = np.mean(all_nn_distances)
            print(f"    平均: {avg_nn:.3f} Å")
            print(f"    範囲: {min(all_nn_distances):.3f} - {max(all_nn_distances):.3f} Å")

    # 構造の比較
    print("\n\n【構造比較】")
    print("=" * 80)
    print(f"{'構造':<15} {'空間群':<15} {'密度 (g/cm³)':<15} {'最近接距離 (Å)'}")
    print("-" * 80)

    for name, structure in structures.items():
        try:
            sga = SpacegroupAnalyzer(structure)
            sg = sga.get_space_group_symbol()
        except:
            sg = "N/A"

        neighbors = structure.get_neighbors(structure[0], 4.0)
        if neighbors:
            nn_dist = min([neighbor[1] for neighbor in neighbors])
        else:
            nn_dist = 0.0

        print(f"{name:<15} {sg:<15} {structure.density:<15.3f} {nn_dist:.3f}")

    print("=" * 80)
    print("\n✓ pymatgenによる解析が完了しました")

    # CIF形式で保存
    print("\n構造をCIF形式で保存:")
    for name, structure in structures.items():
        filename = name.replace(' ', '_').replace('(', '').replace(')', '') + '.cif'
        structure.to(filename=filename, fmt='cif')
        print(f"  ✓ {filename}")

except ImportError:
    print("エラー: pymatgenがインストールされていません")
    print("インストール方法: pip install pymatgen")
    print("\npymatgenは材料科学研究で広く使われているライブラリで、以下の機能があります:")
    print("  - 結晶構造の生成・操作・解析")
    print("  - 空間群・点群の自動判定")
    print("  - Materials Projectデータベースへのアクセス")
    print("  - 密度汎関数理論(DFT)計算との連携")
    print("  - 相図・状態図の計算")

演習問題

演習 1.1

Easy

問題:銅(Cu)の電子密度は $n = 8.45 \times 10^{28}$ m⁻³、緩和時間は $\tau = 2.5 \times 10^{-14}$ s です。Drudeモデルを用いて銅の電気伝導度 $\sigma$ と電気抵抗率 $\rho$ を計算してください。

解答を表示
import numpy as np

# 物理定数
e = 1.602e-19  # 電子の電荷 (C)
m_e = 9.109e-31  # 電子の質量 (kg)

# 銅のパラメータ
n = 8.45e28  # 電子密度 (m^-3)
tau = 2.5e-14  # 緩和時間 (s)

# 電気伝導度の計算
sigma = (n * e**2 * tau) / m_e

# 電気抵抗率の計算
rho = 1 / sigma

print("=" * 60)
print("銅の電気伝導度と電気抵抗率(Drudeモデル)")
print("=" * 60)
print(f"\n与えられた値:")
print(f"  電子密度 n:    {n:.2e} m^-3")
print(f"  緩和時間 τ:    {tau:.2e} s")
print(f"\n計算結果:")
print(f"  電気伝導度 σ:  {sigma:.3e} S/m")
print(f"  電気抵抗率 ρ:  {rho:.3e} Ω·m")
print(f"                 {rho * 1e8:.2f} μΩ·cm")
print(f"\n参考: 実測値は約 1.68 μΩ·cm(室温)")
print("=" * 60)

# 説明
print("\n【計算の説明】")
print("-" * 60)
print("Drudeモデルの電気伝導度の式:")
print("  σ = (n × e² × τ) / m")
print("\nここで、")
print("  n  : 電子密度")
print("  e  : 電子の電荷 (1.602 × 10⁻¹⁹ C)")
print("  τ  : 緩和時間(電子が散乱されるまでの平均時間)")
print("  m  : 電子の質量 (9.109 × 10⁻³¹ kg)")
print("\n電気抵抗率は電気伝導度の逆数:")
print("  ρ = 1 / σ")
print("-" * 60)

# 検証
print("\n【結果の検証】")
print("-" * 60)
theoretical = rho * 1e8
experimental = 1.68
error = abs(theoretical - experimental) / experimental * 100
print(f"理論値(Drudeモデル): {theoretical:.2f} μΩ·cm")
print(f"実測値(室温):         {experimental:.2f} μΩ·cm")
print(f"誤差:                   {error:.1f}%")
print("\nDrudeモデルは古典的な近似ですが、")
print("オーダーは合っており、金属の電気伝導性を")
print("定性的に説明できることがわかります。")
print("=" * 60)

演習 1.2

Easy

問題:FCC構造において、格子定数 $a = 4.05$ Åのとき、以下を計算してください:

  1. 原子半径 $r$
  2. 充填率
  3. 単位格子あたりの原子数
解答を表示
import numpy as np

# 格子定数
a = 4.05  # Å

print("=" * 70)
print("FCC構造の計算問題")
print("=" * 70)
print(f"\n与えられた値:")
print(f"  格子定数 a = {a} Å")

# (1) 原子半径の計算
# FCC では、面対角線上に原子が接触している
# 面対角線の長さ = 4r = a√2
r = a / (2 * np.sqrt(2))

print(f"\n(1) 原子半径の計算:")
print(f"    FCC構造では、面対角線上に原子が接触しています。")
print(f"    面対角線の長さ = 4r = a√2")
print(f"    したがって、r = a / (2√2)")
print(f"    ")
print(f"    計算: r = {a} / (2√2)")
print(f"           = {a} / {2 * np.sqrt(2):.4f}")
print(f"           = {r:.4f} Å")

# (2) 充填率の計算
# 単位格子あたりの原子数
n_atoms = 4

# 単位格子の体積
V_cell = a**3

# 原子の体積(球として)
V_atom = (4/3) * np.pi * r**3

# 充填率
packing_fraction = (n_atoms * V_atom) / V_cell

print(f"\n(2) 充填率の計算:")
print(f"    単位格子あたりの原子数: n = {n_atoms}")
print(f"    単位格子の体積: V_cell = a³ = {a}³ = {V_cell:.3f} ų")
print(f"    原子1個の体積: V_atom = (4/3)πr³ = {V_atom:.3f} ų")
print(f"    ")
print(f"    充填率 = (n × V_atom) / V_cell")
print(f"           = ({n_atoms} × {V_atom:.3f}) / {V_cell:.3f}")
print(f"           = {packing_fraction:.4f}")
print(f"           = {packing_fraction * 100:.2f}%")

# 理論値との比較
theoretical_packing = np.pi / (3 * np.sqrt(2))
print(f"    ")
print(f"    理論値: π / (3√2) = {theoretical_packing:.4f} = {theoretical_packing * 100:.2f}%")

# (3) 単位格子あたりの原子数
print(f"\n(3) 単位格子あたりの原子数:")
print(f"    頂点の原子: 8個の頂点 × 1/8 = 1個")
print(f"    面心の原子: 6個の面 × 1/2 = 3個")
print(f"    合計:       1 + 3 = {n_atoms}個")

# まとめ
print("\n" + "=" * 70)
print("【解答まとめ】")
print("=" * 70)
print(f"(1) 原子半径 r:              {r:.4f} Å = {r * 100:.2f} pm")
print(f"(2) 充填率:                  {packing_fraction:.4f} = {packing_fraction * 100:.2f}%")
print(f"(3) 単位格子あたりの原子数:  {n_atoms}個")
print("=" * 70)

# 補足情報
print("\n【補足】")
print("-" * 70)
print("FCC構造の特徴:")
print("  - 最密充填構造の一つ(充填率 74%)")
print("  - 配位数: 12")
print("  - すべり系が多く、延性が高い")
print("  - 代表的な金属: Cu, Al, Au, Ag, Ni, Pb")
print("-" * 70)

演習 1.3

Medium

問題:立方晶系の結晶において、格子定数 $a = 3.5$ Å のとき、以下の面の面間隔を計算してください:$(100)$, $(110)$, $(111)$, $(200)$, $(220)$

解答を表示
import numpy as np
import matplotlib.pyplot as plt

def calculate_d_spacing(a, h, k, l):
    """
    立方晶系の面間隔を計算

    Parameters:
    -----------
    a : float
        格子定数 (Å)
    h, k, l : int
        ミラー指数

    Returns:
    --------
    d : float
        面間隔 (Å)
    """
    d = a / np.sqrt(h**2 + k**2 + l**2)
    return d

# 格子定数
a = 3.5  # Å

# 計算する面
planes = [
    (1, 0, 0),
    (1, 1, 0),
    (1, 1, 1),
    (2, 0, 0),
    (2, 2, 0)
]

print("=" * 80)
print("立方晶系における面間隔の計算")
print("=" * 80)
print(f"\n与えられた値:")
print(f"  格子定数 a = {a} Å")
print(f"\n立方晶系の面間隔の公式:")
print(f"  d_hkl = a / √(h² + k² + l²)")

print(f"\n計算結果:")
print("=" * 80)
print(f"{'(hkl)':<8} {'h²+k²+l²':<12} {'√(h²+k²+l²)':<18} {'d_hkl (Å)':<15}")
print("-" * 80)

d_values = []
plane_labels = []

for h, k, l in planes:
    sum_squares = h**2 + k**2 + l**2
    sqrt_sum = np.sqrt(sum_squares)
    d = calculate_d_spacing(a, h, k, l)
    d_values.append(d)
    plane_labels.append(f"({h}{k}{l})")

    print(f"({h}{k}{l}){'':<5} {sum_squares:<12} {sqrt_sum:<18.4f} {d:.4f}")

print("=" * 80)

# 面間隔の可視化
fig, ax = plt.subplots(figsize=(12, 7))

colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8']
bars = ax.bar(plane_labels, d_values, color=colors, alpha=0.8, edgecolor='black', linewidth=2)

ax.set_ylabel('面間隔 d (Å)', fontsize=13, fontweight='bold')
ax.set_xlabel('ミラー指数 (hkl)', fontsize=13, fontweight='bold')
ax.set_title(f'立方晶系の面間隔(a = {a} Å)', fontsize=15, fontweight='bold', pad=15)
ax.grid(axis='y', alpha=0.3, linestyle='--')

# バーに数値を表示
for bar, d in zip(bars, d_values):
    height = bar.get_height()
    ax.text(bar.get_x() + bar.get_width()/2., height + 0.05,
            f'{d:.3f} Å', ha='center', va='bottom', fontsize=11, fontweight='bold')

plt.tight_layout()
plt.savefig('d_spacing_comparison.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n✓ グラフを 'd_spacing_comparison.png' として保存しました")

# X線回折への応用
print("\n【X線回折への応用】")
print("=" * 80)
print("Braggの法則: 2d sinθ = nλ")
print(f"\nCu Kα線(λ = 1.5418 Å)を使った場合の回折角 2θ:")
print("-" * 80)

lambda_cu = 1.5418  # Å

for (h, k, l), d in zip(planes, d_values):
    if d > lambda_cu / 2:  # Bragg条件を満たす場合のみ
        sin_theta = lambda_cu / (2 * d)
        theta = np.arcsin(sin_theta) * 180 / np.pi
        two_theta = 2 * theta
        print(f"({h}{k}{l}):  d = {d:.4f} Å  →  2θ = {two_theta:.2f}°")
    else:
        print(f"({h}{k}{l}):  d = {d:.4f} Å  →  回折なし(λ/2 より小さい)")

print("=" * 80)

# 面間隔の順序
print("\n【面間隔の順序】")
print("-" * 80)
sorted_indices = np.argsort(d_values)[::-1]  # 降順
print("面間隔の大きい順:")
for i, idx in enumerate(sorted_indices):
    h, k, l = planes[idx]
    print(f"  {i+1}. ({h}{k}{l}): {d_values[idx]:.4f} Å")
print("-" * 80)

演習 1.4

Medium

問題:銅(Cu)のフェルミエネルギーは 7.05 eV です。以下を計算してください:

  1. 絶対零度(0 K)と室温(300 K)におけるフェルミ-ディラック分布を計算し、グラフで比較してください
  2. フェルミ速度(フェルミエネルギーに対応する電子の速度)を計算してください
解答を表示
import numpy as np
import matplotlib.pyplot as plt
from scipy import constants

# 物理定数
k_B = constants.k  # ボルツマン定数 (J/K)
e = constants.e  # 電子の電荷 (C)
m_e = constants.m_e  # 電子の質量 (kg)

# 銅のフェルミエネルギー
E_F_eV = 7.05  # eV
E_F = E_F_eV * e  # J に変換

print("=" * 80)
print("銅のフェルミ-ディラック分布とフェルミ速度の計算")
print("=" * 80)
print(f"\n与えられた値:")
print(f"  フェルミエネルギー E_F = {E_F_eV} eV = {E_F:.3e} J")

# (1) フェルミ-ディラック分布の計算
def fermi_dirac(E, E_F, T):
    """
    フェルミ-ディラック分布関数

    Parameters:
    -----------
    E : array-like
        エネルギー (J)
    E_F : float
        フェルミエネルギー (J)
    T : float
        温度 (K)

    Returns:
    --------
    f : array-like
        占有確率
    """
    if T == 0:
        return np.where(E <= E_F, 1.0, 0.0)
    else:
        # オーバーフロー対策
        x = (E - E_F) / (k_B * T)
        x = np.clip(x, -100, 100)
        return 1 / (1 + np.exp(x))

# エネルギー範囲(eV単位で設定)
E_range_eV = np.linspace(0, 15, 1000)
E_range = E_range_eV * e  # J に変換

# 0 K と 300 K での分布
f_0K = fermi_dirac(E_range, E_F, 0)
f_300K = fermi_dirac(E_range, E_F, 300)

# プロット
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))

# 左図: 分布関数の比較
ax1.plot(E_range_eV, f_0K, 'b-', linewidth=2.5, label='T = 0 K')
ax1.plot(E_range_eV, f_300K, 'r-', linewidth=2.5, label='T = 300 K')
ax1.axvline(E_F_eV, color='green', linestyle='--', linewidth=2, label=f'$E_F$ = {E_F_eV} eV')
ax1.fill_between(E_range_eV, 0, f_300K, alpha=0.2, color='red')
ax1.set_xlabel('エネルギー (eV)', fontsize=12, fontweight='bold')
ax1.set_ylabel('占有確率 f(E)', fontsize=12, fontweight='bold')
ax1.set_title('フェルミ-ディラック分布の温度依存性', fontsize=13, fontweight='bold')
ax1.legend(fontsize=11)
ax1.grid(True, alpha=0.3)
ax1.set_xlim(0, 15)
ax1.set_ylim(-0.05, 1.05)

# 右図: フェルミエネルギー付近の拡大図
E_zoom_eV = np.linspace(E_F_eV - 1, E_F_eV + 1, 500)
E_zoom = E_zoom_eV * e
f_zoom_0K = fermi_dirac(E_zoom, E_F, 0)
f_zoom_300K = fermi_dirac(E_zoom, E_F, 300)

ax2.plot(E_zoom_eV, f_zoom_0K, 'b-', linewidth=2.5, label='T = 0 K')
ax2.plot(E_zoom_eV, f_zoom_300K, 'r-', linewidth=2.5, label='T = 300 K')
ax2.axvline(E_F_eV, color='green', linestyle='--', linewidth=2, label=f'$E_F$ = {E_F_eV} eV')
ax2.axhline(0.5, color='gray', linestyle=':', linewidth=1.5, alpha=0.7)
ax2.set_xlabel('エネルギー (eV)', fontsize=12, fontweight='bold')
ax2.set_ylabel('占有確率 f(E)', fontsize=12, fontweight='bold')
ax2.set_title('フェルミエネルギー付近の拡大図', fontsize=13, fontweight='bold')
ax2.legend(fontsize=11)
ax2.grid(True, alpha=0.3)
ax2.set_xlim(E_F_eV - 1, E_F_eV + 1)
ax2.set_ylim(-0.05, 1.05)

plt.tight_layout()
plt.savefig('fermi_dirac_temperature_comparison.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n(1) フェルミ-ディラック分布:")
print("-" * 80)
print(f"  0 K:   E < E_F ではすべての状態が占有 (f = 1)")
print(f"         E > E_F ではすべての状態が空 (f = 0)")
print(f"         ステップ関数として振る舞う")
print(f"  ")
print(f"  300 K: E = E_F で f = 0.5")
print(f"         熱エネルギー k_B T = {k_B * 300 / e * 1000:.2f} meV 程度の幅で")
print(f"         分布が「ぼける」")
print(f"         しかし、E_F = {E_F_eV} eV >> k_B T なので、")
print(f"         ステップ関数に近い形を保つ")

# (2) フェルミ速度の計算
# E_F = (1/2) m v_F^2 より v_F = √(2 E_F / m)
v_F = np.sqrt(2 * E_F / m_e)

print(f"\n(2) フェルミ速度の計算:")
print("-" * 80)
print(f"  フェルミエネルギーと電子の運動エネルギーの関係:")
print(f"    E_F = (1/2) m v_F²")
print(f"  ")
print(f"  したがって、フェルミ速度は:")
print(f"    v_F = √(2 E_F / m)")
print(f"  ")
print(f"  計算:")
print(f"    v_F = √(2 × {E_F:.3e} J / {m_e:.3e} kg)")
print(f"        = {v_F:.3e} m/s")
print(f"        = {v_F / 1e6:.3f} × 10⁶ m/s")
print(f"  ")
print(f"  光速 c = {constants.c:.3e} m/s との比:")
print(f"    v_F / c = {v_F / constants.c:.4f} = {v_F / constants.c * 100:.2f}%")
print("-" * 80)

print("\n" + "=" * 80)
print("【解答まとめ】")
print("=" * 80)
print(f"(1) フェルミ-ディラック分布:")
print(f"    - 0 K ではステップ関数")
print(f"    - 300 K では E_F 付近で k_B T 程度の幅でぼける")
print(f"    - グラフを 'fermi_dirac_temperature_comparison.png' に保存")
print(f"")
print(f"(2) フェルミ速度:")
print(f"    v_F = {v_F / 1e6:.3f} × 10⁶ m/s (光速の約 {v_F / constants.c * 100:.1f}%)")
print("=" * 80)

print("\n【物理的意義】")
print("-" * 80)
print("フェルミ速度は、絶対零度においてフェルミエネルギーを持つ")
print("電子の速度です。この速度は非常に大きく(約 10⁶ m/s)、")
print("金属中の電子が高速で運動していることを示しています。")
print("これが金属の高い電気伝導性と熱伝導性の原因です。")
print("-" * 80)

演習 1.5

Hard

問題:FCC構造の金属において、$(111)$ 面と $(100)$ 面のすべり系(すべり面とすべり方向の組み合わせ)を特定し、それぞれの面での原子配列密度を比較してください。どちらの面がすべりやすいか、理由とともに説明してください。

解答を表示
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

print("=" * 80)
print("FCC金属のすべり系解析:(111)面 vs (100)面")
print("=" * 80)

# FCC構造のすべり系
print("\n【FCC構造のすべり系】")
print("-" * 80)
print("FCC金属(Cu, Al, Au, Ag, Niなど)の主要なすべり系:")
print("  すべり面: {111} 面(最密充填面)")
print("  すべり方向: <110> 方向(最密充填方向)")
print("  ")
print("(111)面のすべり系: 4つの{111}面 × 3つの<110>方向 = 12個")
print("(100)面のすべり系: 通常はすべらないが、高温では活性化")

# (111)面と(100)面の原子配列密度の計算
print("\n【原子配列密度の比較】")
print("-" * 80)

# 格子定数
a = 1.0  # 任意単位

# (111)面の原子配列密度
# (111)面は正三角形の格子
# 三角形の面積 = (√3/2) × (a/√2)² = (√3/4) × a²
area_111_triangle = (np.sqrt(3) / 4) * a**2

# (111)面の単位三角形には1個の原子が含まれる
# (頂点の3個 × 1/3 = 1個)
atoms_per_triangle_111 = 1

# 原子配列密度 = 原子数 / 面積
density_111 = atoms_per_triangle_111 / area_111_triangle

print(f"\n(111)面の解析:")
print(f"  格子構造: 正三角形格子(最密充填)")
print(f"  単位三角形の面積: (√3/4) × a² = {area_111_triangle:.4f} a²")
print(f"  単位三角形あたりの原子数: {atoms_per_triangle_111}")
print(f"  原子配列密度: {density_111:.4f} / a²")
print(f"                = {density_111:.4f} × (1/a²)")

# (100)面の原子配列密度
# (100)面は正方格子
# 正方形の面積 = (a/√2)² = a²/2
area_100_square = a**2 / 2

# (100)面の単位正方形には1個の原子が含まれる
# (頂点の4個 × 1/4 = 1個)
atoms_per_square_100 = 1

# 原子配列密度
density_100 = atoms_per_square_100 / area_100_square

print(f"\n(100)面の解析:")
print(f"  格子構造: 正方格子")
print(f"  単位正方形の面積: a²/2 = {area_100_square:.4f} a²")
print(f"  単位正方形あたりの原子数: {atoms_per_square_100}")
print(f"  原子配列密度: {density_100:.4f} / a²")
print(f"                = {density_100:.4f} × (1/a²)")

# 比較
ratio = density_111 / density_100
print(f"\n原子配列密度の比:")
print(f"  (111)面 / (100)面 = {ratio:.4f}")
print(f"  (111)面は(100)面の {ratio:.2f}倍 密に原子が配列")

# すべりやすさの評価
print("\n" + "=" * 80)
print("【すべりやすさの評価】")
print("=" * 80)

print("\n(111)面が主要なすべり面である理由:")
print("-" * 80)
print(f"1. 最密充填面である")
print(f"   → 原子配列密度が最も高い ({density_111:.4f} / a²)")
print(f"   → 原子間結合が強く、面全体として安定")
print(f"")
print(f"2. 面間隔が最も大きい")
print(f"   → d_111 = a / √3 = {a / np.sqrt(3):.4f} a")
print(f"   → d_100 = a / √1 = {a / np.sqrt(1):.4f} a")
print(f"   → 面間隔が大きいほど、すべりに必要なせん断応力が小さい")
print(f"")
print(f"3. すべり方向 <110> が最密充填方向")
print(f"   → 原子間距離が最短 (a/√2 = {a / np.sqrt(2):.4f} a)")
print(f"   → すべりの際の原子の移動距離が最小")
print(f"")
print(f"4. すべり系の数が多い")
print(f"   → {111} 面: 4面 × 3方向 = 12個のすべり系")
print(f"   → 多様な応力方向に対応可能 → 延性が高い")

print("\n(100)面がすべりにくい理由:")
print("-" * 80)
print(f"1. 原子配列密度が低い ({density_100:.4f} / a²)")
print(f"   → (111)面の {1/ratio:.2f}倍")
print(f"   → 面全体としての結合が弱い")
print(f"")
print(f"2. 面間隔が小さい")
print(f"   → d_100 = {a / np.sqrt(1):.4f} a ((111)面の {np.sqrt(3):.2f}倍密)")
print(f"   → すべりに必要なせん断応力が大きい")
print(f"")
print(f"3. 常温では活性化しない")
print(f"   → 高温(>0.5T_m)で初めて活性化")

# 臨界分解せん断応力(CRSS)の概念
print("\n" + "=" * 80)
print("【臨界分解せん断応力(CRSS)】")
print("=" * 80)

print("\nSchmidの法則:")
print("  τ_R = σ cos φ cos λ")
print("  ")
print("  ここで、")
print("  τ_R : 分解せん断応力")
print("  σ  : 引張応力")
print("  φ  : 応力軸とすべり面法線のなす角")
print("  λ  : 応力軸とすべり方向のなす角")
print("  ")
print("すべりが開始する条件:")
print("  τ_R ≥ τ_CRSS")
print("  ")
print("FCC金属の典型的なCRSS値(室温):")
print("  Cu:  約 0.5 - 1.0 MPa")
print("  Al:  約 0.2 - 0.5 MPa")
print("  Au:  約 0.3 - 0.8 MPa")

# 可視化:すべり系の模式図
fig = plt.figure(figsize=(14, 6))

# 左図: (111)面のすべり系
ax1 = fig.add_subplot(121, projection='3d')
ax1.set_title('(111)面のすべり系\n(最密充填面、12個のすべり系)',
              fontsize=12, fontweight='bold', pad=15)

# (111)面を描画(簡略化)
plane_vertices_111 = np.array([
    [0, 0, 1],
    [1, 0, 0],
    [0, 1, 0]
])

# 面を描画
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
poly_111 = Poly3DCollection([plane_vertices_111], alpha=0.5,
                             facecolor='cyan', edgecolor='blue', linewidth=2)
ax1.add_collection3d(poly_111)

# すべり方向のベクトルを描画
slip_directions_111 = [
    ([0, 0, 1], [1, 0, 0]),
    ([1, 0, 0], [0, 1, 0]),
    ([0, 1, 0], [0, 0, 1])
]

for start, end in slip_directions_111:
    start = np.array(start)
    end = np.array(end)
    ax1.quiver(start[0], start[1], start[2],
               end[0] - start[0], end[1] - start[1], end[2] - start[2],
               color='red', arrow_length_ratio=0.2, linewidth=2)

ax1.set_xlabel('X', fontsize=10, fontweight='bold')
ax1.set_ylabel('Y', fontsize=10, fontweight='bold')
ax1.set_zlabel('Z', fontsize=10, fontweight='bold')
ax1.set_xlim([0, 1])
ax1.set_ylim([0, 1])
ax1.set_zlim([0, 1])

# 右図: (100)面のすべり系
ax2 = fig.add_subplot(122, projection='3d')
ax2.set_title('(100)面のすべり系\n(非最密充填面、常温では不活性)',
              fontsize=12, fontweight='bold', pad=15)

# (100)面を描画
plane_vertices_100 = np.array([
    [1, 0, 0],
    [1, 1, 0],
    [1, 1, 1],
    [1, 0, 1]
])

poly_100 = Poly3DCollection([plane_vertices_100], alpha=0.5,
                             facecolor='lightcoral', edgecolor='red', linewidth=2)
ax2.add_collection3d(poly_100)

ax2.set_xlabel('X', fontsize=10, fontweight='bold')
ax2.set_ylabel('Y', fontsize=10, fontweight='bold')
ax2.set_zlabel('Z', fontsize=10, fontweight='bold')
ax2.set_xlim([0, 1])
ax2.set_ylim([0, 1])
ax2.set_zlim([0, 1])

plt.tight_layout()
plt.savefig('fcc_slip_systems_comparison.png', dpi=300, bbox_inches='tight')
plt.show()

print("\n" + "=" * 80)
print("【結論】")
print("=" * 80)
print("(111)面が(100)面よりすべりやすい理由:")
print("  1. 最密充填面であり、原子配列密度が高い")
print(f"     → (111): {density_111:.4f} / a²")
print(f"     → (100): {density_100:.4f} / a² ({ratio:.2f}倍の差)")
print("  2. 面間隔が大きく、すべりに必要なせん断応力が小さい")
print("  3. すべり系が12個と多く、多様な応力に対応可能")
print("  4. FCC金属の高い延性の主要因")
print("=" * 80)

print("\n✓ グラフを 'fcc_slip_systems_comparison.png' として保存しました")

学習目標の確認

レベル1: 基本理解(知識の習得)

  • 金属結合の自由電子モデルとDrudeモデルを説明できる
  • FCC、BCC、HCP結晶構造の違いを説明できる
  • 充填率と配位数の意味を理解している
  • フェルミ-ディラック分布の概念を理解している
  • ミラー指数の表記方法を理解している

レベル2: 実践スキル(計算と応用)

  • Drudeモデルで電気伝導度を計算できる
  • FCC、BCC、HCP構造の充填率を計算できる
  • ミラー指数から面間隔を計算できる
  • フェルミエネルギーとフェルミ速度を計算できる
  • Pythonで結晶構造を可視化できる
  • ASEやpymatgenを使って結晶構造を生成・操作できる

レベル3: 応用力(問題解決と最適化)

  • 結晶構造から材料の機械的性質を予測できる
  • すべり系を解析し、材料の延性を評価できる
  • 実験データ(XRD、電気抵抗率など)を結晶構造と関連付けて解釈できる
  • pymatgenやASEを使って材料設計シミュレーションを実行できる
  • Materials Projectなどのデータベースを活用して材料探索ができる

参考文献

  1. Kittel, C. (2018). Introduction to Solid State Physics, 9th ed. Wiley, pp. 145-189, 223-267.
  2. Ashcroft, N.W., Mermin, N.D. (1976). Solid State Physics. Brooks Cole, pp. 1-48, 123-167.
  3. Callister, W.D., Jr., Rethwisch, D.G. (2020). Materials Science and Engineering: An Introduction, 10th ed. Wiley, pp. 45-89, 112-145.
  4. Porter, D.A., Easterling, K.E., Sherif, M.Y. (2009). Phase Transformations in Metals and Alloys, 3rd ed. CRC Press, pp. 1-35.
  5. Cottrell, A.H. (1953). Dislocations and Plastic Flow in Crystals. Oxford University Press, pp. 8-34.
  6. Hosford, W.F. (2010). Mechanical Behavior of Materials, 2nd ed. Cambridge University Press, pp. 67-102.
  7. pymatgen documentation: Structure module. https://pymatgen.org/pymatgen.core.structure.html
  8. ASE (Atomic Simulation Environment) documentation: Atoms and lattice objects. https://wiki.fysik.dtu.dk/ase/